首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Spring 3.1中使用remember-me功能登录用户

在Spring 3.1中使用remember-me功能登录用户
EN

Stack Overflow用户
提问于 2011-10-18 20:05:08
回答 2查看 9.8K关注 0票数 17

我目前以编程方式登录用户(例如,当他们通过Facebook或使用我的登录表单以外的其他方式登录时):

代码语言:javascript
复制
SecurityContextHolder.getContext().setAuthentication(
  new UsernamePasswordAuthenticationToken(user, "", authorities)
);

我想要做的是让用户登录,就像他们在登录表单中设置了remember-me选项一样。所以我猜我需要使用RememberMeAuthenticationToken而不是UsernamePasswordAuthenticationToken?但是对于构造函数的key参数,我应该怎么做呢?

代码语言:javascript
复制
RememberMeAuthenticationToken(String key, Object principal, Collection<? extends GrantedAuthority> authorities) 

更新:我正在使用Persistent Token Approach described here。因此,没有像简单的基于散列的令牌方法那样的键。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-19 01:32:55

我假设您已经在配置中设置了<remember-me>

remember-me的工作方式是设置一个cookie,当用户在会话到期后返回站点时,该cookie将被识别。

您必须将正在使用的RememberMeServices (TokenBasedPersistentTokenBased)子类化,并使onLoginSuccess()成为公共的。例如:

代码语言:javascript
复制
public class MyTokenBasedRememberMeServices extends PersistentTokenBasedRememberMeServices {
    @Override
    public void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {
        super.onLoginSuccess(request, response, successfulAuthentication);
    }   
} 

<remember-me services-ref="rememberMeServices"/>

<bean id="rememberMeServices" class="foo.MyTokenBasedRememberMeServices">
    <property name="userDetailsService" ref="myUserDetailsService"/>
    <!-- etc -->
</bean>

将RememberMeServices注入到执行编程登录的bean中。然后使用您创建的UsernamePasswordAuthenticationToken对其调用onLoginSuccess()。这将设置cookie。

代码语言:javascript
复制
UsernamePasswordAuthenticationToken auth = 
    new UsernamePasswordAuthenticationToken(user, "", authorities);
SecurityContextHolder.getContext().setAuthentication(auth);
getRememberMeServices().onLoginSuccess(request, response, auth);  

更新

@at在此基础上进行了改进,没有RememberMeServices:的子类化

代码语言:javascript
复制
UsernamePasswordAuthenticationToken auth = 
    new UsernamePasswordAuthenticationToken(user, "", authorities);
SecurityContextHolder.getContext().setAuthentication(auth);

// This wrapper is important, it causes the RememberMeService to see
// "true" for the "_spring_security_remember_me" parameter.
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
    @Override public String getParameter(String name) { return "true"; }            
};

getRememberMeServices().loginSuccess(wrapper, response, auth);  
票数 14
EN

Stack Overflow用户

发布于 2011-10-18 21:38:15

这是构造函数的源代码。

代码语言:javascript
复制
public RememberMeAuthenticationToken(String key, Object principal, Collection<? extends GrantedAuthority> authorities) {
    super(authorities);

    if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal)) {
        throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
    }

    this.keyHash = key.hashCode();
    this.principal = principal;
    setAuthenticated(true);
}

密钥是散列的,它用于确定在安全上下文中用于该用户的身份验证是否不是“伪造的”身份验证。

请看一下RememberMeAuthenicationProvider源代码。

代码语言:javascript
复制
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    if (!supports(authentication.getClass())) {
        return null;
    }

    if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication).getKeyHash()) {
        throw new BadCredentialsException(messages.getMessage("RememberMeAuthenticationProvider.incorrectKey",
                "The presented RememberMeAuthenticationToken does not contain the expected key"));
    }

    return authentication;
}

因此,为了回答您的问题,您需要传递表示用户keyAuthentication字段的散列代码。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7806921

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档