开源项目一手文档基本都在github,标准文档基本都在官网。
最好的文档就是官网;
在前些年,Apache下还有个比较流行的权限框架 Shiro,但是随着Spring Security (以下简称 Security)的流行,逐渐边缘化。其实这类框架整体设计都大差不差,都是基于一系列的过滤器或者其他拦截手段实现增强。
这一块属于 Servlet 基础,过滤器算是Servlet核心功能之一,需重点掌握。
Security 在 Servlet 过滤器上定义了一个 自己的过滤器(这个过滤器使用了委托者设计模式)
可以看到,Servlet 过滤器链上,不仅有 Security 的过滤器还有 Spring Boot 的一些过滤器,但是这里我们重点关注圈起来的那个过滤器(链)
再对比官方的这个图
就更好理解了。
我们自定义的过滤器基本都是在 Security 这个过滤器链上面的,通过编排不同的顺序,实现想要的功能。
在这之前,我们先看看Security默认的过滤器链上有哪些过滤器官方列表
这里为了照顾,访问不了官网的,简单截个图。
但不是所有过滤器默认都开启了的。
上面那个链是,Spring 全局的过滤器链,里面第四个过滤器委托给了下面那个 Security 的过滤器链,在 Security 的过滤器链中,可以看到默认有14个过滤器。
其中有几个重点关注的是:
其他的过滤器根据自己的需求,调整。
在实际开发中,目前通常采用前后端分离的形式;有的前端对Cookie 不太友好;因此,为了统一,大部分开发者会采用 header 认证方式。
这样实现起码会有两个点需要调整
提供一个简单实现,具体业务逻辑,开发者自己填充
package authorization.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token = request.getHeader("token");
if (!StringUtils.hasText(token)) {
filterChain.doFilter(request, response);
return;
}
try {
UsernamePasswordAuthenticationToken authenticationToken
= UsernamePasswordAuthenticationToken.authenticated("zhangsan", "zs", Collections.emptyList());
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authenticationToken);
SecurityContextHolder.setContext(context);
filterChain.doFilter(request, response);
}
finally {
SecurityContextHolder.clearContext();
}
}
@Override
protected boolean shouldNotFilterErrorDispatch() {
return true;
}
}