本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: 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/