• spring boot使用自定义过滤器实现接口认证


    自定义过滤器

    创建MyFilter 类 去实现Filter接口
    根据业务逻辑,来覆写doFilter方法

    
    import com.alibaba.fastjson.JSONObject;
    import com.shxp.project.common.entity.R;
    import com.shxp.project.common.entity.SpringBeanFactoryUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.io.UnsupportedEncodingException;
    
    public class MyFilter implements Filter {
    
        final static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MyFilter.class);
    
        @Autowired
        private CipherFilter cipherFilter;
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            // 打印请求信息
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;
            logger.info("------------- LogFilter 开始 -------------");
            logger.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
            logger.info("远程地址: {}", request.getRemoteAddr());
            long startTime = System.currentTimeMillis();
            // 验证是否成功默认false
            boolean isFilter = false;
            // new一个报错返回实体 
            R r = new R();
            try {
            	// 判断引入的验证方法是否为空,如果为空通过SpringBean的方式引进
                if (cipherFilter == null) {
                    cipherFilter = SpringBeanFactoryUtils.getBean(CipherFilter.class);
                }
                // 验证方法
                isFilter = cipherFilter.handle(request, response);
            } catch (Exception ex) {
    //            e.printStackTrace();
                r.setCode(500);
                r.setMsg(ex.getMessage());
                PrintWriter writer = null;
                OutputStreamWriter osw = null;
                try {
                    osw = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
                    writer = new PrintWriter(osw, true);
                    String json = JSONObject.toJSONString(r);
                    writer.write(json);
                    writer.flush();
                    writer.close();
                    osw.close();
                } catch (UnsupportedEncodingException e) {
                    logger.error("过滤器返回信息失败:" + e.getMessage(), e);
                } catch (IOException e) {
                    logger.error("过滤器返回信息失败:" + e.getMessage(), e);
                } finally {
                    if (null != writer) {
                        writer.close();
                    }
                    if (null != osw) {
                        osw.close();
                    }
                }
                return;
            }
            logger.info("------------- LogFilter 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);
            // 如果验证通过执行
            if (isFilter) {
                chain.doFilter(req, res);
            }
        }
    
        public void init(FilterConfig filterConfig) {
        }
    
    
        public void destroy() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    创建FilterConfig类

    该配置类用于配置你要过滤的过滤路径

    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration //定义此类为配置类,必须增加
    public class FilterConfig {
    
        @Bean
    
        public FilterRegistrationBean myFilterRegistrationBean() {
    
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter());
    
            //添加过滤器路径
    
            filterRegistrationBean.addUrlPatterns("/workflow/*");
            filterRegistrationBean.addUrlPatterns("/system/yyxt/*");
    
    //        filterRegistrationBean.addUrlPatterns("/login/*");
    
            return filterRegistrationBean;
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    加密 解密 验证CipherFilter

    CipherFilter 中主要对过滤接口Header中的值进行:非空判断、数据解密、数据认证

     	public boolean handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
            AuthParam authorityParam = new AuthParam();
            authorityParam.setModuleId(request.getHeader("moduleId"));
            authorityParam.setNonce(request.getHeader("nonce"));
            authorityParam.setSignature(request.getHeader("signature"));
            return handle0(authorityParam);
        }
        
    	public boolean handle0(AuthParam authorityParam) throws Exception {
    
            String moduleId = authorityParam.getModuleId();
            if (StringUtils.isBlank(moduleId)) {
                throw new Exception("moduleId 不允许为空!");
            }
    		// 查询所有外部对接系统信息
            Map<String, SysYyxtVo> map = subSystemService.getSubSystemMap();
            SysYyxtVo subSystem = map.get(moduleId);
            if (subSystem == null) {
                throw new Exception("无法识别的moduleId !");
            }
    
            String nonce = authorityParam.getNonce();
            if (StringUtils.isBlank(nonce)) {
                throw new Exception("nonce 不允许为空!");
            }
    
            String signature = authorityParam.getSignature();
            if (StringUtils.isBlank(signature)) {
                throw new Exception("signature 不允许为空!");
            }
    		// 对数据进行加密判断是否一致
    		// moduleKey 是本系统对外部系统的密钥
            String sig2 = AESUtils.sha1(subSystem.getModulekey(), nonce);
            if (!signature.equals(sig2)) {
                throw new Exception("验证不通过,请检查是否持有正确的moduleKey!");
            }
            return true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    其他工具类

    AES 128 加密工具

    
    import org.apache.commons.codec.digest.DigestUtils;
    import org.springframework.util.Base64Utils;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.UnsupportedEncodingException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.util.UUID;
    
    /**
     * AES 128 加密工具
     */
    public class AESUtils {
    
        public final static String ENCODING="UTF-8";
    
        public final static String KEY_AES="AES";
    
        public static KeyGenerator kgen;
    
        static {
            try {
                kgen = KeyGenerator.getInstance("AES");
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
    
    
        /**
         * AES128 加密
         * @param content 内容
         * @param password 密钥
         * @return 加密后的结果
         */
        public static String aes128Encrypt(String content, String password){
            try{
                Cipher cipher = Cipher.getInstance(KEY_AES);
                byte[] byteContent = content.getBytes(ENCODING);
                SecretKeySpec secretKeySpec = getSecretKeySpec(password);
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
                byte[] result = cipher.doFinal(byteContent);
                return Base64Utils.encodeToString(result);
            }catch (Exception e){
                e.printStackTrace();
            }
    
            return null;
        }
    
        /**
         * AES128 解密
         * @param content 内容
         * @param password 密钥
         * @return 解密后的结果
         */
        public static String aes128Decrypt(String content, String password){
            try{
                Cipher cipher = Cipher.getInstance(KEY_AES);
                SecretKeySpec secretKeySpec = getSecretKeySpec(password);
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
                byte[] byteContent = Base64Utils.decodeFromString(content);
                byte[] result = cipher.doFinal(byteContent);
                return new String(result,ENCODING);
            }catch (Exception e){
                e.printStackTrace();
            }
            return null;
        }
    
        private static SecretKeySpec getSecretKeySpec(String password) throws UnsupportedEncodingException {
            kgen.init(128, new SecureRandom(password.getBytes(ENCODING)));
            return new SecretKeySpec(kgen.generateKey().getEncoded(), KEY_AES);
        }
    
        public static String md5(String text, String key) throws Exception{
            String encodeStr = DigestUtils.md5Hex(text + key);
            return encodeStr;
        }
    
        public static String sha1(String text, String key) throws Exception{
            String encodeStr = DigestUtils.sha1Hex(text + key);
            return encodeStr;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    bean未加载前获取bean

    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    /**
     * bean未加载前获取bean
     */
    @Component
    public class SpringBeanFactoryUtils implements ApplicationContextAware {
        private static ApplicationContext context = null;
    
        //获取bean
        public static <T> T getBean(Class<T> type) {
            return context.getBean(type);
        }
    
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            if (SpringBeanFactoryUtils.context == null) {
                SpringBeanFactoryUtils.context = applicationContext;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    接口效果

    swagger访问

    我们发现通过swagger访问已经不行了
    在这里插入图片描述

    Apipost 错误请求

    我们用apipost 故意写错moduleId
    在这里插入图片描述

    Apipost 正确请求

    在这里插入图片描述

  • 相关阅读:
    关于#网络#的问题:采用CRC方法进行校验,求数据冗余码FCS(相关搜索:计算机网络)
    10.2servlet基础2
    【数据结构】链表详解
    链表——反转链表
    defer和async
    error: #20: identifier “PWMC_Handle_t“ is undefined
    Pillow(PIL)库的主要方法介绍
    找个好用的录屏软件,怎么这么难?
    VS Code 在线运行:code-server部署(系列一)
    深度学习_13_YOLO_图片切片及维度复原
  • 原文地址:https://blog.csdn.net/qq_25391785/article/details/128114558