现在国内前后端很多公司都在使用前后端分离的开发方式,虽然也有很多人并不赞同前后端分离,比如以下这篇博客就很有意思:
https://www.aliyun.com/jiaocheng/650661.html
我们从技术角度来看的话:
http://blog.jobbole.com/111624/
http://www.360doc.com/content/18/0511/06/36490684_752894279.shtml
摘要:
当然,站在我的角度,CTO要求我们用前后端分离我就用好了,前后端分离的权限控制问题要稍微复杂一些,我们最近的项目采用security+jwt的方式来实现前后端分离的权限控制。
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
关于security的其他知识可以看:
https://cloud.tencent.com/developer/article/1954211
Json web token (JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519)。该标准被设计为紧凑且安全的,一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息。当然该标准也可直接被用于认证,也可被加密。
关于JWT可以看下面这篇博客:
https://cloud.tencent.com/developer/article/1196128
spring security + jwt的具体实现思路是:
用户登陆后台,后台生成一个jwt签名返回给前端,前端每次请求将签名放在Header,后台验证签名是否正确。
关于security的部分这里不再赘述
jwt
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
验证token
public class JwtAuthenticationTokenFilter extends UsernamePasswordAuthenticationFilter {
@Autowired
private CustomerUserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
private String tokenHeader="Authorization";
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResopnse = (HttpServletResponse) response;
if("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {
httpResopnse.setStatus(HttpServletResponse.SC_OK);
} else {
String authToken = httpRequest.getHeader(this.tokenHeader);
if(authToken!=null)
authToken =authToken.substring(7);
String username = jwtTokenUtil.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
}
}
JWT工具类中,根据USER信息生成token
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put(CLAIM_KEY_CREATED, new Date());
......
return generateToken(claims);
}
然后前端需要在每次的请求中将这个token放入请求头中。