|  |  |  | 
|---|
|  |  |  | package com.zy.asrs.wms.common.security; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import com.zy.asrs.framework.common.Cools; | 
|---|
|  |  |  | import com.zy.asrs.wms.common.config.ConfigProperties; | 
|---|
|  |  |  | import com.zy.asrs.wms.common.constant.Constants; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.entity.Menu; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.entity.User; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.entity.UserLogin; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.service.UserLoginService; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.service.UserService; | 
|---|
|  |  |  | import com.zy.asrs.wms.utils.HttpUtils; | 
|---|
|  |  |  | import com.zy.asrs.wms.utils.JwtUtil; | 
|---|
|  |  |  | import io.jsonwebtoken.Claims; | 
|---|
|  |  |  | import io.jsonwebtoken.ExpiredJwtException; | 
|---|
|  |  |  | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | 
|---|
|  |  |  | import org.springframework.security.core.context.SecurityContextHolder; | 
|---|
|  |  |  | import org.springframework.security.core.userdetails.UsernameNotFoundException; | 
|---|
|  |  |  | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | 
|---|
|  |  |  | import org.springframework.stereotype.Component; | 
|---|
|  |  |  | import org.springframework.web.filter.OncePerRequestFilter; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import javax.annotation.Resource; | 
|---|
|  |  |  | 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.ArrayList; | 
|---|
|  |  |  | import java.util.Date; | 
|---|
|  |  |  | import java.util.List; | 
|---|
|  |  |  | import java.util.stream.Collectors; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 处理携带token的请求过滤器 | 
|---|
|  |  |  | * | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @Component | 
|---|
|  |  |  | public class JwtAuthenticationFilter extends OncePerRequestFilter { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public static final ArrayList<String> WHITE_LIST = new ArrayList<String>(){ | 
|---|
|  |  |  | private static final long serialVersionUID = 1L; | 
|---|
|  |  |  | { | 
|---|
|  |  |  | add("xltys1995"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | private ConfigProperties configProperties; | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | private UserService userService; | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | private UserLoginService userLoginService; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { | 
|---|
|  |  |  | String access_token = JwtUtil.getAccessToken(request); | 
|---|
|  |  |  | for (String filterPath : SecurityConfig.FILTER_PATH) { | 
|---|
|  |  |  | AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(filterPath); | 
|---|
|  |  |  | if (antPathMatcher.matches(request)) { | 
|---|
|  |  |  | access_token = ""; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if (!Cools.isEmpty(access_token)) { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | User user; | 
|---|
|  |  |  | // 白名单 | 
|---|
|  |  |  | if (WHITE_LIST.contains(access_token)) { | 
|---|
|  |  |  | user = userService.getByUsername("root", 1L); | 
|---|
|  |  |  | if (user == null) { | 
|---|
|  |  |  | throw new UsernameNotFoundException("Username not found"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | List<Menu> authorities = user.getAuthorities().stream() | 
|---|
|  |  |  | .filter(m -> !Cools.isEmpty(m.getAuthority())).collect(Collectors.toList()); | 
|---|
|  |  |  | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( | 
|---|
|  |  |  | user, null, authorities); | 
|---|
|  |  |  | SecurityContextHolder.getContext().setAuthentication(authentication); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | // 解析token | 
|---|
|  |  |  | Claims claims = JwtUtil.parseToken(access_token, configProperties.getTokenKey()); | 
|---|
|  |  |  | JwtSubject jwtSubject = JwtUtil.getJwtSubject(claims); | 
|---|
|  |  |  | user = userService.getByUsername(jwtSubject.getUsername(), jwtSubject.getHostId()); | 
|---|
|  |  |  | if (user == null) { | 
|---|
|  |  |  | throw new UsernameNotFoundException("Username not found"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | List<Menu> authorities = user.getAuthorities().stream() | 
|---|
|  |  |  | .filter(m -> !Cools.isEmpty(m.getAuthority())).collect(Collectors.toList()); | 
|---|
|  |  |  | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( | 
|---|
|  |  |  | user, null, authorities); | 
|---|
|  |  |  | SecurityContextHolder.getContext().setAuthentication(authentication); | 
|---|
|  |  |  | // token将要过期签发新token, 防止突然退出登录 | 
|---|
|  |  |  | long expiration = (claims.getExpiration().getTime() - new Date().getTime()) / 1000 / 60; | 
|---|
|  |  |  | if (expiration < configProperties.getTokenRefreshTime()) { | 
|---|
|  |  |  | String token = JwtUtil.buildToken(jwtSubject, configProperties.getTokenExpireTime(), | 
|---|
|  |  |  | configProperties.getTokenKey()); | 
|---|
|  |  |  | response.addHeader(Constants.TOKEN_HEADER_NAME, token); | 
|---|
|  |  |  | userLoginService.saveAsync(user.getId(), token, UserLogin.TYPE_REFRESH, user.getHostId(), null, request); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } catch (ExpiredJwtException e) { | 
|---|
|  |  |  | e.printStackTrace(); | 
|---|
|  |  |  | HttpUtils.responseError(response, Constants.TOKEN_EXPIRED_CODE, Constants.TOKEN_EXPIRED_MSG, | 
|---|
|  |  |  | e.getMessage()); | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } catch (Exception e) { | 
|---|
|  |  |  | e.printStackTrace(); | 
|---|
|  |  |  | HttpUtils.responseError(response, Constants.BAD_CREDENTIALS_CODE, Constants.BAD_CREDENTIALS_MSG, | 
|---|
|  |  |  | e.toString()); | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | chain.doFilter(request, response); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | package com.zy.asrs.wms.common.security; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
|---|
|  |  |  | import com.zy.asrs.common.domain.enums.LoginSystemType; | 
|---|
|  |  |  | import com.zy.asrs.framework.common.Cools; | 
|---|
|  |  |  | import com.zy.asrs.wms.common.config.ConfigProperties; | 
|---|
|  |  |  | import com.zy.asrs.wms.common.constant.Constants; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.entity.Menu; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.entity.Role; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.entity.User; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.entity.UserLogin; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.service.UserLoginService; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.service.UserRoleService; | 
|---|
|  |  |  | import com.zy.asrs.wms.system.service.UserService; | 
|---|
|  |  |  | import com.zy.asrs.wms.utils.HttpUtils; | 
|---|
|  |  |  | import com.zy.asrs.wms.utils.JwtUtil; | 
|---|
|  |  |  | import io.jsonwebtoken.Claims; | 
|---|
|  |  |  | import io.jsonwebtoken.ExpiredJwtException; | 
|---|
|  |  |  | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | 
|---|
|  |  |  | import org.springframework.security.core.context.SecurityContextHolder; | 
|---|
|  |  |  | import org.springframework.security.core.userdetails.UsernameNotFoundException; | 
|---|
|  |  |  | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | 
|---|
|  |  |  | import org.springframework.stereotype.Component; | 
|---|
|  |  |  | import org.springframework.web.filter.OncePerRequestFilter; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import javax.annotation.Resource; | 
|---|
|  |  |  | 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.ArrayList; | 
|---|
|  |  |  | import java.util.Date; | 
|---|
|  |  |  | import java.util.List; | 
|---|
|  |  |  | import java.util.stream.Collectors; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 处理携带token的请求过滤器 | 
|---|
|  |  |  | * | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @Component | 
|---|
|  |  |  | public class JwtAuthenticationFilter extends OncePerRequestFilter { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public static final ArrayList<String> WHITE_LIST = new ArrayList<String>(){ | 
|---|
|  |  |  | private static final long serialVersionUID = 1L; | 
|---|
|  |  |  | { | 
|---|
|  |  |  | add("xltys1995"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | private ConfigProperties configProperties; | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | private UserService userService; | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | private UserLoginService userLoginService; | 
|---|
|  |  |  | @Resource | 
|---|
|  |  |  | private UserRoleService userRoleService; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { | 
|---|
|  |  |  | String access_token = JwtUtil.getAccessToken(request); | 
|---|
|  |  |  | for (String filterPath : SecurityConfig.FILTER_PATH) { | 
|---|
|  |  |  | AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(filterPath); | 
|---|
|  |  |  | if (antPathMatcher.matches(request)) { | 
|---|
|  |  |  | access_token = ""; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if (!Cools.isEmpty(access_token)) { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | User user; | 
|---|
|  |  |  | // 白名单 | 
|---|
|  |  |  | if (WHITE_LIST.contains(access_token)) { | 
|---|
|  |  |  | user = userService.getByUsername("root", 1L); | 
|---|
|  |  |  | if (user == null) { | 
|---|
|  |  |  | throw new UsernameNotFoundException("Username not found"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | List<Menu> authorities = user.getAuthorities().stream() | 
|---|
|  |  |  | .filter(m -> !Cools.isEmpty(m.getAuthority())).collect(Collectors.toList()); | 
|---|
|  |  |  | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( | 
|---|
|  |  |  | user, null, authorities); | 
|---|
|  |  |  | SecurityContextHolder.getContext().setAuthentication(authentication); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | // 解析token | 
|---|
|  |  |  | Claims claims = JwtUtil.parseToken(access_token, configProperties.getTokenKey()); | 
|---|
|  |  |  | JwtSubject jwtSubject = JwtUtil.getJwtSubject(claims); | 
|---|
|  |  |  | user = userService.getByUsername(jwtSubject.getUsername(), jwtSubject.getHostId()); | 
|---|
|  |  |  | if (user == null) { | 
|---|
|  |  |  | throw new UsernameNotFoundException("Username not found"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | boolean root = false; | 
|---|
|  |  |  | List<Role> roles = userRoleService.listByUserId(user.getId()); | 
|---|
|  |  |  | for (Role role : roles) { | 
|---|
|  |  |  | if (role.getId() == 1) { | 
|---|
|  |  |  | root = true; | 
|---|
|  |  |  | break; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | UserLogin userLogin = null; | 
|---|
|  |  |  | if (root) { | 
|---|
|  |  |  | userLogin = userLoginService.superFindByUserId(user.getId(), String.valueOf(LoginSystemType.WMS)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<Menu> authorities = user.getAuthorities().stream() | 
|---|
|  |  |  | .filter(m -> !Cools.isEmpty(m.getAuthority())).collect(Collectors.toList()); | 
|---|
|  |  |  | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( | 
|---|
|  |  |  | userLogin == null ? user : userLogin, null, authorities); | 
|---|
|  |  |  | SecurityContextHolder.getContext().setAuthentication(authentication); | 
|---|
|  |  |  | // token将要过期签发新token, 防止突然退出登录 | 
|---|
|  |  |  | long expiration = (claims.getExpiration().getTime() - new Date().getTime()) / 1000 / 60; | 
|---|
|  |  |  | if (expiration < configProperties.getTokenRefreshTime()) { | 
|---|
|  |  |  | String token = JwtUtil.buildToken(jwtSubject, configProperties.getTokenExpireTime(), | 
|---|
|  |  |  | configProperties.getTokenKey()); | 
|---|
|  |  |  | response.addHeader(Constants.TOKEN_HEADER_NAME, token); | 
|---|
|  |  |  | userLoginService.saveAsync(user.getId(), token, UserLogin.TYPE_REFRESH, user.getHostId(), null, request); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } catch (ExpiredJwtException e) { | 
|---|
|  |  |  | e.printStackTrace(); | 
|---|
|  |  |  | HttpUtils.responseError(response, Constants.TOKEN_EXPIRED_CODE, Constants.TOKEN_EXPIRED_MSG, | 
|---|
|  |  |  | e.getMessage()); | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } catch (Exception e) { | 
|---|
|  |  |  | e.printStackTrace(); | 
|---|
|  |  |  | HttpUtils.responseError(response, Constants.BAD_CREDENTIALS_CODE, Constants.BAD_CREDENTIALS_MSG, | 
|---|
|  |  |  | e.toString()); | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | chain.doFilter(request, response); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|