新建com.itheima.stock.security.filter.JwtAuthorizationFilter
package com.itheima.stock.security.filter; import com.fasterxml.jackson.databind.ObjectMapper; import com.itheima.stock.utils.JwtTokenUtil; import com.itheima.stock.vo.resp.R; import com.itheima.stock.vo.resp.ResponseCode; import io.jsonwebtoken.Claims; import org.apache.commons.lang3.StringUtils; import org.springframework.http.MediaType; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContextHolder; 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.List; /** * 授权过滤器,相当于检票员 */ public class JwtAuthorizationFilter extends OncePerRequestFilter {//OncePerRequestFilter:对每个请求只会执行一次过滤 @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String tokenStr = request.getHeader(JwtTokenUtil.TOKEN_HEADER); if (StringUtils.isBlank(tokenStr)) { filterChain.doFilter(request, response); return; } response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); Claims claims = JwtTokenUtil.checkJWT(tokenStr); if (claims == null) { R<Object> error = R.error(ResponseCode.INVALID_TOKEN); response.getWriter().write(new ObjectMapper().writeValueAsString(error)); return; } String username = JwtTokenUtil.getUsername(tokenStr); //["P5","ROLE_ADMIN"] String roles = JwtTokenUtil.getUserRole(tokenStr); //去除[] String strip = StringUtils.strip(roles, "[]"); //把以逗号分隔的字符串转换成GrantedAuthority对象 List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(strip); //null为密码,认证通过后security会将密码置为null UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, null, authorities); //把authenticationToken存入securityContext,以便后续过滤器使用 SecurityContextHolder.getContext().setAuthentication(authenticationToken); //后续的过滤器发现上下文中存在token信息,会认为用户已经通过认证 filterChain.doFilter(request, response); } }
在SecurityConfig类中配置
@Override public void configure(HttpSecurity http) throws Exception { /* 其他代码 */ //配置登录认证过滤器的执行顺序 http.addFilterBefore(jwtLoginAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); //配置授权过滤器的执行顺序 http.addFilterBefore(jwtAuthorizationFilter(), JwtLoginAuthenticationFilter.class); } /** * 配置授权过滤器 * @return */ @Bean public JwtAuthorizationFilter jwtAuthorizationFilter(){ return new JwtAuthorizationFilter(); }
不携带token测试
携带token测试