本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: https://www.huangyunkun.com/2016/03/02/spring-security-form-to-token/
对于任何需要认证的系统,Spring Security无疑是一个很好的选择。
无论是从认证本身,还是权限控制,Spring Security都有极好的支持。
Form登录是一种极为常见的方式,用户输入用户名和密码,post登录信息,认证之后登录信息保存在session之中。
但是随着架构演进,前后端逐渐分离,之前的大部分逻辑都变成了API供前端调用,而Form登录逐渐成为累赘,调试上的困难。这个时候就可以考虑换为token模式,进而将后端API stateless化。
Token的生成和解析
第一步是选择token的生成和解析,我们来个简单的,token中只包含加密后的用户名,具体生成才是JWT的HS512加密。
先配置一个登录成功后的响应AuthSuccessHandler
public class AuthSuccessHandler implements AuthenticationSuccessHandler {
public static final String SECRET_KEY = "0Qx*@S7q";
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
response.setStatus(HttpStatus.OK.value());
JsonNodeFactory factory = JsonNodeFactory.instance;
ObjectNode objectNode = factory.objectNode();
objectNode.set("status", factory.textNode("success"));
objectNode.set("token", factory.textNode(createToken(authentication)));
PrintWriter out = response.getWriter();
out.write(objectNode.toString());
out.close();
}
private String createToken(Authentication authentication) {
return Jwts.builder()
.setSubject(authentication.getName())
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
}
配置中添加一句
and().formLogin().successHandler(new AuthSuccessHandler())
这样登录成功后会返回类似这样的json
{
"status": "success",
"token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ4aWFuIn0.O5xEDP5JCMcrQzpRaswsrhWfZ1Wlw7r8-94KU14G6wN_nSKH0YZZprKaoiuiNIRXWbmkX68KFx2fts1DPbPnOw"
}
Token认证
现在我们有了token,任何消费API的请求都需要在header中包含这个token,然后再根据这个token给予用户的请求完成认证,Spring Security的Pre-Auth就是合适的方案。
当我们获取token以后直接解码获得用户名,并给予当前访问认证。
final String token = request.getHeader(AUTH_HEADER_NAME);
if (!StringUtils.isEmpty(token)) {
String username = Jwts.parser()
.setSigningKey(AuthSuccessHandler.SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
if (username!= null) {
logger.info(String.format("User login in with user name: %s", username));
return new UsernamePasswordAuthenticationToken(username, "", Lists.<GrantedAuthority>newArrayList());
}
}
return null;
这个一个Filter,它的位置位于UsernamePasswordAuthenticationFilter之前,在配置中直接配置
.addFilterBefore(new TokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
这样就完成了token的认证,只要请求包含有效的token,那么就能访问授权后的资源。
其他
这只是一个简单的例子,token的生成方式非常脆弱,也没有过期超时等等的验证。Spring Security还有oauth模块,可以使用其中的tokenStore等等去完善。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: https://www.huangyunkun.com/2016/03/02/spring-security-form-to-token/