传参统一jwt加密(坑)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 传参统一jwt加密(坑)

说明

这个涉及到的主要是和前端约定加密方式,我这边主动采用了jwt方式,原因吗就不解释了。

实现起来大致思想就是做拦截,之前尝试了一版注解方式,做了一半想到一个问题。。注解拦截的参数是已经绑定之后的了。。要是自己再去处理的话就会非常麻烦。。

后来果断放弃,想了想还是使用过滤方便,想着只要把请求参数改了不就行了,实际上这样确实是可行的,就是有个坑,得同时修改getParamNames方法,不然参数是绑定不了的

先说实现吧

定义一个过滤器

package com.fedtech.common.filter.jwt;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
 * 将约定的请求头参数使用jwt转化为普通参数,供系统使用
 *
 * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >
 * @date 2021/2/9
 * @since 1.0.0
 */
@Component
public class JwtFilter implements Filter {
    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
            throws IOException, ServletException {
        ParameterRequestWrapper paramsRequest = new ParameterRequestWrapper((HttpServletRequest) arg0);
        String[] secretParams = paramsRequest.getParameterMap().get("secretParam");
        if (secretParams == null) {
            arg2.doFilter(arg0, arg1);
        } else {
            arg2.doFilter(paramsRequest, arg1);
        }
    }
    @Override
    public void init(FilterConfig arg0) {
    }
    @Override
    public void destroy() {
    }
}

重写获取参数相关的方法

package com.fedtech.common.filter.jwt;
import com.alibaba.fastjson.JSON;
import com.fedtech.common.util.StringJsonUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.util.WebUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static com.fedtech.common.constants.Request.RequestConstants.CONTENT_TYPE;
import static org.apache.commons.lang3.StringUtils.equalsAny;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/**
 * 1. 接口请求过滤去除前后空格
 * 2. 解析jwt参数
 *
 * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >
 * @date 2021/1/26
 * @since 1.0.0
 */
@Slf4j
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
    /**
     * 这个东东就是request.getParam()的params
     */
    private final Map<String, String[]> params = new HashMap<>();
    /**
     * 解析jwt就是在这边做的,主要思想就是修改params,毕竟官方没提供setParam方法
     * 该方法还同时对参数前后空格做了处理
     *
     * @param request 请求
     *
     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >
     * @date 2021/2/9
     * @since 1.0.0
     */
    public ParameterRequestWrapper(HttpServletRequest request) {
        // 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
        super(request);
        //将参数表,赋予给当前的Map以便于持有request中的参数
        Map<String, String[]> requestMap = new HashMap<>(request.getParameterMap());
        //这边拿到和前端约定的参数名
        String[] secretParams = requestMap.get("secretParam");
        if (secretParams == null) {
            return;
        }
        String secretParam = secretParams[0];
        //没有加密参数的话就不处理了
        if (isNotBlank(secretParam)) {
            //jwt解析一波
            Jws<Claims> jws = Jwts.parser()
                    .setSigningKey("secret".getBytes(StandardCharsets.UTF_8))
                    .parseClaimsJws(secretParam);
            //这边只要过滤掉几个不需要的参数就行啦啦啦啦!!!!
            jws.getBody().forEach((x, y) -> {
                if (!equalsAny(x, "sub", "exp", "lat", "jti", "iat")) {
                    requestMap.put(x, new String[]{String.valueOf(y)});
                }
            });
        }
        //在这边全部存起来哈!!
        this.params.putAll(requestMap);
        //这个是div的,去除前后空格
        this.modifyParameterValues();
    }
    /**
     * 重写getInputStream方法  post类型的请求参数必须通过流才能获取到值
     *
     * @return javax.servlet.ServletInputStream
     *
     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >
     * @date 2021/2/9
     * @since 1.0.0
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        //非json类型,直接返回
        if (!super.getHeader(CONTENT_TYPE).equalsIgnoreCase("json")) {
            return super.getInputStream();
        }
        //为空,直接返回
        String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8);
        if (StringUtils.isEmpty(json)) {
            return super.getInputStream();
        }
        log.info("转化前参数:{}", json);
        Map<String, Object> map = StringJsonUtils.jsonStringToMap(json);
        log.info("转化后参数:{}", JSON.toJSONString(map));
        ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8));
        return new MyServletInputStream(bis);
    }
    /**
     * 将parameter的值去除空格并且空串返回 null值
     *
     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >
     * @date 2021/2/9
     * @since 1.0.0
     */
    private void modifyParameterValues() {
        Set<String> set = params.keySet();
        for (String key : set) {
            String[] values = params.get(key);
            String[] newValues = new String[values.length];
            for (int i = 0; i < values.length; i++) {
                newValues[i] = values[i].trim();
                if (newValues[i].length() <= 0) {
                    newValues[i] = null;
                }
            }
            params.put(key, newValues);
        }
    }
    /**
     * 这个吗是最主要的,去看mvn解析链的话,在{@link WebUtils#getParametersStartingWith(ServletRequest, String)}这个里面获取参数就是走的这个方法
     *
     * @return java.util.Enumeration<java.lang.String>
     *
     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >
     * @date 2021/2/9
     * @since 1.0.0
     */
    @Override
    public Enumeration<String> getParameterNames() {
        Vector<String> vector = new Vector<>(params.keySet());
        return vector.elements();
    }
    /**
     * 重写getParameter 参数从当前类中的map获取
     *
     * @return java.lang.String
     *
     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >
     * @date 2021/2/9
     * @since 1.0.0
     */
    @Override
    public String getParameter(String name) {
        String[] values = params.get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }
    /**
     * 重写getParameterValues
     *
     * @return java.lang.String[]
     *
     * @author <a href = "mailto:njpkhuan@gmail.com" > huan </a >
     * @date 2021/2/9
     * @since 1.0.0
     */
    @Override
    public String[] getParameterValues(String name) {//同上
        return params.get(name);
    }
    static class MyServletInputStream extends ServletInputStream {
        private final ByteArrayInputStream bis;
        public MyServletInputStream(ByteArrayInputStream bis) {
            this.bis = bis;
        }
        @Override
        public boolean isFinished() {
            return true;
        }
        @Override
        public boolean isReady() {
            return true;
        }
        @Override
        public void setReadListener(ReadListener listener) {
        }
        @Override
        public int read() {
            return bis.read();
        }
    }
}

这边就说下入口和重点方法吧

SpringMVC源码之参数解析绑定原理 - leanring - 博客园

Debug最后找到获取参数的地方,这个方法是必须重写的,不然绑定的时候是拿不到的


相关文章
|
11天前
|
存储 安全 Java
|
3月前
|
JSON 算法 API
【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token
【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token
|
3月前
|
安全 Nacos 数据安全/隐私保护
【技术干货】破解Nacos安全隐患:连接用户名与密码明文传输!掌握HTTPS、JWT与OAuth2.0加密秘籍,打造坚不可摧的微服务注册与配置中心!从原理到实践,全方位解析如何构建安全防护体系,让您从此告别数据泄露风险!
【8月更文挑战第15天】Nacos是一款广受好评的微服务注册与配置中心,但其连接用户名和密码的明文传输成为安全隐患。本文探讨加密策略提升安全性。首先介绍明文传输风险,随后对比三种加密方案:HTTPS简化数据保护;JWT令牌减少凭证传输,适配分布式环境;OAuth2.0增强安全,支持多授权模式。每种方案各有千秋,开发者需根据具体需求选择最佳实践,确保服务安全稳定运行。
262 0
|
6月前
|
算法 Java 数据安全/隐私保护
如何使用 RSA 加密 JWT
如何使用 RSA 加密 JWT
97 0
|
存储 安全 算法
十七.SpringCloud+Security+Oauth2实现微服务授权 -非对称加密生成JWT令牌
SpringCloud+Security+Oauth2实现微服务授权 -非对称加密生成JWT令牌
|
数据库 数据安全/隐私保护
jwt默认加密,过期时间,使用rsa加密demo
jwt默认加密,过期时间,使用rsa加密demo
239 0
jwt默认加密,过期时间,使用rsa加密demo
|
1天前
|
安全 网络安全 数据安全/隐私保护
数字堡垒的裂缝与钥匙——网络安全漏洞、加密技术与安全意识的博弈
【10月更文挑战第28天】在数字化时代的浪潮中,网络世界如同一座座坚固的堡垒,保护着数据的安全和隐私。然而,这些堡垒并非不可攻破。网络安全漏洞的存在,如同隐藏在城墙之下的裂缝,时刻威胁着堡垒的安全。而加密技术,则是守护这些堡垒的金钥匙,它能够将信息转化为只有授权者才能解读的密文,确保通信的安全。但是,即便有了最先进的加密技术,如果缺乏足够的安全意识,这座堡垒也会变得脆弱不堪。因此,了解网络安全漏洞、掌握加密技术,并培养良好的安全意识,是我们在数字世界中保护自己的重要手段。
|
1天前
|
SQL 安全 算法
网络安全与信息安全:漏洞、加密技术与安全意识的交织
【10月更文挑战第28天】在数字时代的浪潮中,网络安全与信息安全成为保护个人隐私和企业资产的重要盾牌。本文将深入探讨网络安全中的常见漏洞,介绍加密技术的基本概念及其在保护数据中的应用,并强调提高安全意识的重要性。通过分析具体案例和提供实用的防护措施,旨在为读者提供一个全面的网络安全知识框架,以应对日益复杂的网络威胁。
11 4
|
1天前
|
SQL 安全 测试技术
网络安全的盾牌与剑——漏洞防御与加密技术解析
【10月更文挑战第28天】 在数字时代的浪潮中,网络空间安全成为我们不可忽视的战场。本文将深入探讨网络安全的核心问题,包括常见的网络安全漏洞、先进的加密技术以及提升个人和组织的安全意识。通过实际案例分析和代码示例,我们将揭示黑客如何利用漏洞进行攻击,展示如何使用加密技术保护数据,并强调培养网络安全意识的重要性。让我们一同揭开网络安全的神秘面纱,为打造更加坚固的数字防线做好准备。
15 3
|
1天前
|
安全 网络安全 量子技术
网络安全漏洞的阴影与加密技术的盾牌
互联网充满无限可能,但也隐藏着诸多安全风险。网络安全漏洞如同潜伏的阴影,威胁着我们的隐私和安全。加密技术作为一道坚不可摧的盾牌,通过将数据转换为密文,有效保护了信息的安全。本文将探讨对称加密和非对称加密的原理及其应用,帮助我们更好地理解加密技术如何守护数字时代的安全。
7 3