request、response、filterChain,經過本身的過濾邏輯後,再把request、response塞入filterChain丟給下一個Filter。public final void doFilter(ServletRequest request,
ServletResponse response,
FilterChain filterChain
) throws ServletException, IOException {
//...省略
}
OncePerRequestFilter,它是一個抽象類別,而我們需要覆寫其中的doFilterInternal來設計過濾邏輯!但先讓我來釐清一下何謂 OncePerRequestFilter :轉發、錯誤處理 等在 同一Http請求下 的動作,會觸發 多次 Filter。OncePerRequestFilter 這個類別,利用標記法,先「確認該請求是否過濾過」,來決定是否放行!SecurityContextHolder 完成設定。filterChain.doFilter(request,response) 交給下一個Filter執行。@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final UserService userService;
@Value("${secret}")
private String secret;
@Autowired
public JwtAuthenticationFilter(UserService userService){
this.userService = userService;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException{
//* 取出原始token
String rawToken = request.getHeader("Authorization");
//* 若token有問題,交由後續Filter決定是否放行
if (rawToken == null || !rawToken.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
String token = JwtUtil.decode(rawToken);
try{
JwtUtil.verify(token, secret);
String account = JwtUtil.getString(token, "account");
if (account != null && SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails userDetails = userService.loadUserByUsername(account);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}catch (Exception e){
System.out.println("Exception : " + e.getMessage());
}
filterChain.doFilter(request, response);
}
}
本篇文章出自《每天學Java直到今年結束》Day231,大家可以到我的網站上查看~