CeDo
2021-05-01 a7d2d03fe177a58c22e960e9c87b32f7b05be74f
springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/java/com/panzhihua/zuul/filters/JWTAuthenticationTokenFilter.java
@@ -1,176 +1,193 @@
package com.panzhihua.zuul.filters;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.panzhihua.common.constants.*;
import com.panzhihua.common.model.vos.LoginUserInfoVO;
import com.panzhihua.common.model.vos.R;
import com.panzhihua.common.service.user.UserService;
import com.panzhihua.common.utlis.AES;
import com.panzhihua.common.utlis.JWTTokenUtil;
import com.panzhihua.common.utlis.ResultUtil;
import io.jsonwebtoken.Claims;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
 * @program: springcloud_k8s_panzhihuazhihuishequ
 * @description: token校验
 * @author: huang.hongfa weixin hhf9596 qq 959656820
 * @create: 2020-11-25 16:35
 **/
@Component
public class JWTAuthenticationTokenFilter implements Filter {
    private StringRedisTemplate stringRedisTemplate;
    private UserService userService;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    /**
     * 用户是否登录校验
     *
     * @param servletRequest  请求
     * @param servletResponse 返回
     * @param filterChain     过滤器链条
     * @throws IOException      io
     * @throws ServletException servlet
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        ServletContext context = request.getServletContext();
        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);
        stringRedisTemplate=ctx.getBean(StringRedisTemplate.class);
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        userService=ctx.getBean(UserService.class);
        String requestURI = request.getRequestURI();
        boolean login = requestURI.contains("login");
        boolean doc = requestURI.contains("doc.html");
        boolean css = requestURI.contains(".css");
        boolean js = requestURI.contains(".js");
        boolean ui = requestURI.contains("/ui");
        boolean swagger = requestURI.contains("swagger");
        boolean ico = requestURI.contains(".ico");
        boolean docs = requestURI.contains("-docs");
        boolean error = requestURI.contains("error");
        boolean useragreement = requestURI.contains("useragreement");
        boolean refreshToken = requestURI.contains("refreshToken");
        boolean logout = requestURI.contains("logout");
        boolean wxPay = requestURI.contains("wxNotify");
        boolean wxCgi = requestURI.contains("cgi");
        boolean isShop = requestURI.contains("isShop");
        boolean listadvertisement = requestURI.contains("listadvertisement");
        SafeboxRequestWrapper safeboxRequestWrapper = new SafeboxRequestWrapper(request);
        if (login||doc||css||js||ui||swagger||ico||docs||error||refreshToken||useragreement||wxPay||wxCgi||isShop||listadvertisement) {
            //什么也不做
        } else {
            // 获取请求头中JWT的Token
            String tokenHeader = request.getHeader(TokenConstant.TOKEN_HEADER);
            if (null != tokenHeader && tokenHeader.startsWith(TokenConstant.TOKEN_PRE)) {
                // token过期
                String token = tokenHeader.replace(TokenConstant.TOKEN_PRE, "");
                Boolean hasKey = stringRedisTemplate.hasKey(UserConstants.LOGOUT_TOKEN + token);
                if (hasKey) {
                    ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "用户已经登出"));
                    return;
                }
                Boolean expired = JWTTokenUtil.isTokenExpired(token);
                if (expired) {
                    if (logout) {
                        ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "登出成功"));
                    } else {
                        ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "token过期"));
                    }
                    return;
                }
                // token解析
                Claims claims = JWTTokenUtil.getClaimsFromToken(token);
                if (ObjectUtils.isEmpty(claims)) {
                    ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "token校验失败"));
                    return;
                }
                String username = claims.getSubject();
                int type = (Integer) claims.get("type");
                if (ObjectUtils.isEmpty(username)) {
                    ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "token校验失败"));
                    return;
                }
                List<SimpleGrantedAuthority> authorities = new ArrayList<>();
                List<SimpleGrantedAuthority> authorities1 = new ArrayList<>();
                String key = SecurityConstants.ROLE_USER + username;
                Boolean aBoolean = stringRedisTemplate.hasKey(key);
                if (1 == type) {//小程序用户统一角色
                    authorities.add(new SimpleGrantedAuthority(SecurityConstants.ROLE_APPLETS));
                } else {
                    if (aBoolean) {
                        String roles = valueOperations.get(key);
                        authorities = JSONArray.parseArray(roles, SimpleGrantedAuthority.class);
                    } else {
                        R<List<String>> r = userService.getUserRoles(username);
                        List<String> data =(List<String>)r.getData();
                        if (!ObjectUtils.isEmpty(data)) {
                            data.forEach(s -> {
                                authorities1.add(new SimpleGrantedAuthority(s));
                            });
                            authorities = authorities1;
                            valueOperations.set(key, JSONArray.toJSONString(authorities), 24, TimeUnit.HOURS);
                        }
                    }
                }
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, username, authorities);//主要使用权限 账户 密码 不重要
                SecurityContextHolder.getContext().setAuthentication(authentication);
                safeboxRequestWrapper.addHeader(TokenConstant.TOKEN_LOGOUT,tokenHeader);
                //登录用户的所有信息
                String userKey = UserConstants.LOGIN_USER_INFO + username;
                Boolean hasKeyLoginUserInfo = stringRedisTemplate.hasKey(userKey);
                if(hasKeyLoginUserInfo){
                    String userInfo = valueOperations.get(userKey);
                    byte[] encrypt = AES.encrypt(userInfo, Constants.AES_KEY);
                    String hexStr = AES.parseByte2HexStr(encrypt);
                    safeboxRequestWrapper.addHeader(TokenConstant.TOKEN_USERINFO, hexStr);
                }else{
                    R<LoginUserInfoVO> r = userService.getUserInfoByUserId(username);
                    if (!R.isOk(r)) {
                        ResultUtil.responseJson(response, R.fail(HttpStatus.ERROR, "登录用户信息查询失败"));
                        return;
                    }
                    LoginUserInfoVO data = r.getData();
                    String userInfo = JSONObject.toJSONString(data);
                    valueOperations.set(userKey,userInfo,24,TimeUnit.HOURS);
                    byte[] encrypt = AES.encrypt(userInfo, Constants.AES_KEY);
                    String hexStr = AES.parseByte2HexStr(encrypt);
                    safeboxRequestWrapper.addHeader(TokenConstant.TOKEN_USERINFO,hexStr );
                }
            } else {
                ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "token校验失败"));
                return;
            }
        }
        filterChain.doFilter(safeboxRequestWrapper,response);
        }
    @Override
    public void destroy() {
    }
}
package com.panzhihua.zuul.filters;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.panzhihua.common.constants.*;
import com.panzhihua.common.model.vos.LoginUserInfoVO;
import com.panzhihua.common.model.vos.R;
import com.panzhihua.common.service.user.UserService;
import com.panzhihua.common.utlis.AES;
import com.panzhihua.common.utlis.JWTTokenUtil;
import com.panzhihua.common.utlis.ResultUtil;
import io.jsonwebtoken.Claims;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
 * @program: springcloud_k8s_panzhihuazhihuishequ
 * @description: token校验
 * @author: huang.hongfa weixin hhf9596 qq 959656820
 * @create: 2020-11-25 16:35
 **/
@Component
public class JWTAuthenticationTokenFilter implements Filter {
    private StringRedisTemplate stringRedisTemplate;
    private UserService userService;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    /**
     * 用户是否登录校验
     *
     * @param servletRequest  请求
     * @param servletResponse 返回
     * @param filterChain     过滤器链条
     * @throws IOException      io
     * @throws ServletException servlet
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        ServletContext context = request.getServletContext();
        ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);
        stringRedisTemplate=ctx.getBean(StringRedisTemplate.class);
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        userService=ctx.getBean(UserService.class);
        String requestURI = request.getRequestURI();
        boolean login = requestURI.contains("login");
        boolean doc = requestURI.contains("doc.html");
        boolean css = requestURI.contains(".css");
        boolean js = requestURI.contains(".js");
        boolean ui = requestURI.contains("/ui");
        boolean swagger = requestURI.contains("swagger");
        boolean ico = requestURI.contains(".ico");
        boolean docs = requestURI.contains("-docs");
        boolean error = requestURI.contains("error");
        boolean useragreement = requestURI.contains("useragreement");
        boolean refreshToken = requestURI.contains("refreshToken");
        boolean logout = requestURI.contains("logout");
        boolean wxPay = requestURI.contains("wxNotify");
        boolean wxCgi = requestURI.contains("cgi");
        boolean isShop = requestURI.contains("isShop");
        boolean listadvertisement = requestURI.contains("listadvertisement");
        SafeboxRequestWrapper safeboxRequestWrapper = new SafeboxRequestWrapper(request);
        if (login||doc||css||js||ui||swagger||ico||docs||error||refreshToken||useragreement||wxPay||wxCgi||isShop||listadvertisement) {
            //什么也不做
        } else {
            // 获取请求头中JWT的Token
            String tokenHeader = request.getHeader(TokenConstant.TOKEN_HEADER);
            if (null != tokenHeader && tokenHeader.startsWith(TokenConstant.TOKEN_PRE)) {
                // token过期
                String token = tokenHeader.replace(TokenConstant.TOKEN_PRE, "");
                Boolean hasKey = stringRedisTemplate.hasKey(UserConstants.LOGOUT_TOKEN + token);
                if (hasKey) {
                    ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "用户已经登出"));
                    return;
                }
                Boolean expired = JWTTokenUtil.isTokenExpired(token);
                if (expired) {
                    if (logout) {
                        ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "登出成功"));
                    } else {
                        ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "token过期"));
                    }
                    return;
                }
                // token解析
                Claims claims = JWTTokenUtil.getClaimsFromToken(token);
                if (ObjectUtils.isEmpty(claims)) {
                    ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "token校验失败"));
                    return;
                }
                String username = claims.getSubject();
                int type = (Integer) claims.get("type");
                if (ObjectUtils.isEmpty(username)) {
                    ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "token校验失败"));
                    return;
                }
                List<SimpleGrantedAuthority> authorities = new ArrayList<>();
                List<SimpleGrantedAuthority> authorities1 = new ArrayList<>();
                if (1 == type) {//小程序用户统一角色
                    String roleAppletKey = SecurityConstants.ROLE_APPLETS_USER +username;
                    if(stringRedisTemplate.hasKey(roleAppletKey)){
                        String roles = valueOperations.get(roleAppletKey);
                        authorities = JSONArray.parseArray(roles, SimpleGrantedAuthority.class);
                    }else {
                        authorities.add(new SimpleGrantedAuthority(SecurityConstants.ROLE_APPLETS));
                        String userKey = UserConstants.LOGIN_USER_INFO + username;
                        Boolean hasKeyLoginUserInfo = stringRedisTemplate.hasKey(userKey);
                        if (hasKeyLoginUserInfo) {
                            String userInfo = valueOperations.get(userKey);
                            LoginUserInfoVO loginUserInfoVO = JSONObject.parseObject(userInfo, LoginUserInfoVO.class);
                            //判断用户是否已实名制
                            if (loginUserInfoVO.getIsRealNamed() != null && loginUserInfoVO.getIsRealNamed()) {
                                authorities.add(new SimpleGrantedAuthority(SecurityConstants.ROLE_APPLETS_REAL_NAMED));
                            }
                        }
                        valueOperations.set(roleAppletKey, JSONArray.toJSONString(authorities), 24, TimeUnit.HOURS);
                    }
                } else {
                    String key = SecurityConstants.ROLE_USER + username;
                    Boolean aBoolean = stringRedisTemplate.hasKey(key);
                    if (aBoolean) {
                        String roles = valueOperations.get(key);
                        authorities = JSONArray.parseArray(roles, SimpleGrantedAuthority.class);
                    } else {
                        R<List<String>> r = userService.getUserRoles(username);
                        List<String> data =(List<String>)r.getData();
                        if (!ObjectUtils.isEmpty(data)) {
                            data.forEach(s -> {
                                authorities1.add(new SimpleGrantedAuthority(s));
                            });
                            authorities = authorities1;
                            valueOperations.set(key, JSONArray.toJSONString(authorities), 24, TimeUnit.HOURS);
                        }
                    }
                }
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, username, authorities);//主要使用权限 账户 密码 不重要
                SecurityContextHolder.getContext().setAuthentication(authentication);
                safeboxRequestWrapper.addHeader(TokenConstant.TOKEN_LOGOUT,tokenHeader);
                //登录用户的所有信息
                String userKey = UserConstants.LOGIN_USER_INFO + username;
                Boolean hasKeyLoginUserInfo = stringRedisTemplate.hasKey(userKey);
                if(hasKeyLoginUserInfo){
                    String userInfo = valueOperations.get(userKey);
                    byte[] encrypt = AES.encrypt(userInfo, Constants.AES_KEY);
                    String hexStr = AES.parseByte2HexStr(encrypt);
                    safeboxRequestWrapper.addHeader(TokenConstant.TOKEN_USERINFO, hexStr);
                }else{
                    R<LoginUserInfoVO> r = userService.getUserInfoByUserId(username);
                    if (!R.isOk(r)) {
                        ResultUtil.responseJson(response, R.fail(HttpStatus.ERROR, "登录用户信息查询失败"));
                        return;
                    }
                    LoginUserInfoVO data = r.getData();
                    String userInfo = JSONObject.toJSONString(data);
                    valueOperations.set(userKey,userInfo,24,TimeUnit.HOURS);
                    byte[] encrypt = AES.encrypt(userInfo, Constants.AES_KEY);
                    String hexStr = AES.parseByte2HexStr(encrypt);
                    safeboxRequestWrapper.addHeader(TokenConstant.TOKEN_USERINFO,hexStr );
                }
            } else {
                ResultUtil.responseJson(response, R.fail(HttpStatus.UNAUTHORIZED, "token校验失败"));
                return;
            }
        }
        filterChain.doFilter(safeboxRequestWrapper,response);
        }
    @Override
    public void destroy() {
    }
}