如何使用 Spring-security 以编程方式登录用户?
Posted
技术标签:
【中文标题】如何使用 Spring-security 以编程方式登录用户?【英文标题】:How to login a user programmatically using Spring-security? 【发布时间】:2014-10-15 21:31:49 【问题描述】:我需要以编程方式登录通过 Facebook API 进行身份验证的用户。原因是每个用户(例如购物车)关联了许多项目,因此一旦用户使用 Facebook API 进行身份验证,我还需要使用 spring security 登录用户才能访问他/她的购物车。
根据我的研究,有很多方法可以实现它,但我无法部署其中任何一个,因为我正在从我的代码发送登录请求,另一个问题是有些人创建了用户对象但他们没有解释如何创建它。
那些创建了用户对象但没有解释如何的人。
来自第一个例子:this answer
Authentication auth =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
来自第二个例子:this one
34.User details = new User(username);
35.token.setDetails(details);
来自第三个例子:this one
Authentication authentication = new UsernamePasswordAuthenticationToken(user, null,
AuthorityUtils.createAuthorityList("ROLE_USER"));
另一个example is here,它没有帮助,因为我需要从我自己的代码而不是浏览器登录用户;因此我不知道如何填充 HttpServletRequest 对象。
protected void automatedLogin(String username, String password, HttpServletRequest request)
我的代码
...
if(isAuthenticatedByFB())
login(username);
return "success";
else
return "failed";
【问题讨论】:
【参考方案1】:不幸的是,Spring 安全中似乎没有“完全”支持编程登录。以下是我成功完成的方法:
@Autowired AuthenticationSuccessHandler successHandler;
@Autowired AuthenticationManager authenticationManager;
@Autowired AuthenticationFailureHandler failureHandler;
public void login(HttpServletRequest request, HttpServletResponse response, String username, String password)
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
token.setDetails(new WebAuthenticationDetails(request));//if request is needed during authentication
Authentication auth;
try
auth = authenticationManager.authenticate(token);
catch (AuthenticationException e)
//if failureHandler exists
try
failureHandler.onAuthenticationFailure(request, response, e);
catch (IOException | ServletException se)
//ignore
throw e;
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(auth);
successHandler.onAuthenticationSuccess(request, response, auth);//if successHandler exists
//if user has a http session you need to save context in session for subsequent requests
HttpSession session = request.getSession(true);
session.setAttribute("SPRING_SECURITY_CONTEXT", securityContext);
更新 Spring的RememberMeAuthenticationFilter.doFilter()
基本相同
【讨论】:
谢谢,请您进一步详细说明。我需要任何 requestHandler 吗?如何配置项目? 我使用典型的 spring 安全配置,它像往常一样用于处理 HTTP 请求。当我需要在内部对用户进行身份验证时,上面的代码在特殊情况下有效。 如何使用 oauth 2.0 进行身份验证? 请问,您在哪里/如何定义提供给session.setAttribute(...)
的securityContext
变量?
@JayEdwards 感谢您的提问,我修复了代码 sn-p【参考方案2】:
此代码来自Grails' Spring Security Core -Plugin,它是在 Apache 2.0 许可下发布的。我添加了导入只是为了指出确切的类型。原作者是伯特·贝克威斯。
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
...
public static void reauthenticate(final String username, final String password)
UserDetailsService userDetailsService = getBean("userDetailsService");
UserCache userCache = getBean("userCache");
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
userDetails, password == null ? userDetails.getPassword() : password, userDetails.getAuthorities()));
userCache.removeUserFromCache(username);
getBean 方法仅提供来自应用程序上下文的 bean。
【讨论】:
所以这实际上验证了所有密码都是真实的,甚至是 badones。以上是关于如何使用 Spring-security 以编程方式登录用户?的主要内容,如果未能解决你的问题,请参考以下文章
spring-security saml2:如何获取当前用户?
Spring-Security:升级到 Spring-Security 4.1 后,用户名发送为空以进行登录