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() {
    }
}

创建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;

    }

}

加密 解密 验证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;
    }

其他工具类

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;
    }
}

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;
        }
    }
}

接口效果

swagger访问

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

Apipost 错误请求

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

Apipost 正确请求

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟进军大神陆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值