package com.common.filter; import com.common.annotation.NoToken; import com.common.core.utils.JwtTokenUtil; import com.common.core.utils.SpringContextUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; 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.*; import java.util.stream.Collectors; /** * @author 廖振钦 * @date 2022-01-17 */ @Slf4j public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { @Autowired private JwtTokenUtil jwtTokenUtil; @Autowired private UserDetailsService userDetailsService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { Map handlerMethods = ((RequestMappingHandlerMapping)SpringContextUtils.getBean("requestMappingHandlerMapping")).getHandlerMethods(); Set anonymousUrls = new HashSet<>(); for (Map.Entry infoEntry : handlerMethods.entrySet()) { // 获取所有接口的方法 HandlerMethod handlerMethod = infoEntry.getValue(); if ( handlerMethod.hasMethodAnnotation(NoToken.class)) { final PatternsRequestCondition requestCondition = infoEntry.getKey().getPatternsCondition(); Optional.ofNullable(requestCondition).orElseThrow(RuntimeException::new); anonymousUrls.addAll(requestCondition.getPatterns().stream().map(m -> SpringContextUtils.getEnvParam("server.servlet.context-path")+m).collect(Collectors.toList())); } } String uri = request.getRequestURI(); boolean visit = true; for(String item : Arrays.asList(new String[]{ ".html", ".css", ".js", ".png", ".ttf", ".ico", ".woff", "/swagger-resources", "/v2/api-docs", "/druid" })){ if(uri.contains(item)){ visit = false; } } if(!anonymousUrls.contains(uri) && !HttpMethod.OPTIONS.matches(request.getMethod()) && visit) { String token = request.getHeader("pi-token"); log.info("TOKEN:"+token); if(StringUtils.isEmpty(token)){ throw new AuthenticationServiceException("TOKEN为空"); } String appid = jwtTokenUtil.getAppidFromToken(token); if (appid != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(appid); if (jwtTokenUtil.validateToken(token, userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); }else{ throw new AuthenticationServiceException("TOKEN无效"); } } } chain.doFilter(request,response); } }