最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring boot實(shí)現(xiàn)在request里解密參數(shù)返回

 更新時(shí)間:2021年09月15日 09:35:02   作者:如漩渦  
這篇文章主要介紹了Spring Boot實(shí)現(xiàn)在request里解密參數(shù)返回操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

spring boot在request里解密參數(shù)返回

前言

有個(gè)業(yè)務(wù)需求,一個(gè)請(qǐng)求來(lái)源web,一個(gè)請(qǐng)求來(lái)源APP,web需求驗(yàn)證簽名,APP的參數(shù)是經(jīng)過加密,所以出現(xiàn)了兩個(gè)Controller,除了解密獲取參數(shù)方式不一樣,其他內(nèi)容一模一樣,這樣不太合理,所以我決定重構(gòu)。

思路:既然只是解密不一樣,獲取到的參數(shù)是一樣的,那可以寫一個(gè)過濾器,在里面就把參數(shù)解密好,然后返回

Spring Boot在請(qǐng)求的時(shí)候是不允許直接修改HttpServletRequest里的paramsMap參數(shù)的,但是提供了一個(gè)HttpServletRequestWrapper類,繼承這個(gè)類重寫兩個(gè)方法就可以了。

代碼塊

重寫HttpServletRequestWrapper

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
public class ParameterRequest extends HttpServletRequestWrapper {
    private Map<String, String[]> params = new HashMap<>(16);
    public ParameterRequest(HttpServletRequest request) throws IOException {
        super(request);
        this.params.putAll(request.getParameterMap());
    }
    /**
     * 重載一個(gè)構(gòu)造方法
     *
     * @param request
     * @param extendParams
     */
    public ParameterRequest(HttpServletRequest request, Map<String, String[]> extendParams) throws IOException {
        this(request);
        addAllParameters(extendParams);
    }
    @Override
    public String getParameter(String name) {
        String[] values = params.get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }
    @Override
    public String[] getParameterValues(String name) {
        return params.get(name);
    }
    public void addAllParameters(Map<String, String[]> otherParams) {
        for (Map.Entry<String, String[]> entry : otherParams.entrySet()) {
            addParameter(entry.getKey(), entry.getValue());
        }
    }
    public void addParameter(String name, Object value) {
        if (value != null) {
            if (value instanceof String[]) {
                params.put(name, (String[]) value);
            } else if (value instanceof String) {
                params.put(name, new String[]{(String) value});
            } else {
                params.put(name, new String[]{String.valueOf(value)});
            }
        }
    }
}

思路是重寫自定義一個(gè)Map存入?yún)?shù),將解密后需要的參數(shù)放入,然后在過濾器中執(zhí)行這個(gè)新的request

過濾器

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
public class WebParamFilter implements Filter {
    private static final String OPTIONS = "OPTIONS";
    @Value("${jwt.info.urlPatterns}")
    private List<String> urlPatterns;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        log.info("開始過濾器===============");
        if (!isFilter(request)) {
            writerError(response, RetEnum.RET_TOKEN_ERROR);
            return;
        }
        // 從請(qǐng)求頭從獲取請(qǐng)求類型,1是WEB,2是APP
        String requestType = request.getHeader("requestType");
        if (StringUtils.isEmpty(requestType)) {
            writerError(response, RetEnum.RET_NOT_HEADER_ERROR);
            return;
        }
        Map<String, String[]> paramsMap = new HashMap<>();
        if ("1".equals(requestType)) {
        	// 驗(yàn)證簽名,簽名錯(cuò)誤直接返回
            if (!compareSign(request)) {
                writerError(response, "簽名錯(cuò)誤", 500);
                return;
            }
            // 將請(qǐng)求的參數(shù)從request中取出,轉(zhuǎn)換成JSON,放入自定義的Map中帶給控制器
            paramsMap.put("params", new String[]{JSONUtil.getJSONParam(request).toJSONString()});
            ParameterRequest req = new ParameterRequest(request, paramsMap);
            filterChain.doFilter(req, response);
        } else if ("2".equals(requestType)) {
        	// APP請(qǐng)求方式比較特殊,所以要從requestBody里讀出JSON加密數(shù)據(jù)
            String bodyStr = RequestBodyUtil.read(request.getReader());
            // 然后再解密,拿到真正的參數(shù)轉(zhuǎn)換成JSON,放入自定義的Map中帶給控制器
            JSONObject jsonParam = getJsonParam(bodyStr);
            paramsMap.put("params", new String[]{jsonParam.toJSONString()});
            ParameterRequest req = new ParameterRequest(request, paramsMap);
            filterChain.doFilter(req, response);
        } else {
            writerError(response, "無(wú)效的請(qǐng)求來(lái)源", 500);
        }
    }
    @Override
    public void destroy() {
    }
    /**
     * 篩選
     *
     * @param request
     * @return
     */
    private boolean isFilter(HttpServletRequest request) {
        if (OPTIONS.equals(request.getMethod())) {
            return true;
        }
        if (isInclude(request)) {
            //如果是屬于排除的URL,比如登錄,注冊(cè),驗(yàn)證碼等URL,則直接通行
            log.info("直接通過");
            return true;
        }
        return tokenCheck(request);
    }
    /**
     * 排除不需要過濾的URL
     *
     * @param request
     * @return
     */
    private boolean isInclude(HttpServletRequest request) {
        String url = request.getRequestURI().substring(request.getContextPath().length());
        log.info("請(qǐng)求url:{}", url);
        for (String patternUrl : urlPatterns) {
            Pattern p = Pattern.compile(patternUrl);
            Matcher m = p.matcher(url);
            if (m.find()) {
                return true;
            }
        }
        return false;
    }
    /**
     * 效驗(yàn)token是否有效
     *
     * @param request
     * @return
     */
    private boolean tokenCheck(HttpServletRequest request) {
        String authToken = request.getHeader("accessToken");
        log.info("請(qǐng)求頭中令牌token:{}", authToken);
        // ...業(yè)務(wù)代碼
        return false;
    }
    /**
     * 錯(cuò)誤寫出
     *
     * @param response
     * @param retEnum
     * @throws IOException
     */
    private void writerError(HttpServletResponse response, String msg, int code) throws IOException {
        //驗(yàn)證不通過
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);
        //將驗(yàn)證不通過的錯(cuò)誤返回
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> resultMap = new HashMap<>(3);
        resultMap.put("code", code);
        resultMap.put("msg", msg);
        resultMap.put("data", null);
        response.getWriter().write(mapper.writeValueAsString(resultMap));
    }
    /**
     * web效驗(yàn)簽名
     *
     * @param request
     * @return
     */
    public boolean compareSign(HttpServletRequest request) {
        JSONObject param = JSONUtil.getJSONParam(request);
        String sign = JSONUtil.getParamRequired(param, String.class, "sign");
       // ...業(yè)務(wù)代碼
        return s.equals(sign);
    }
 	/**
     * APP解密參數(shù)
     *
     * @param json
     * @return
     */
    public JSONObject getJsonParam(String json) {
        JSONObject jsonParam = JSON.parseObject(json);
        String aos = jsonParam.getString("aos");
        String params = jsonParam.getString("params");
        String param = null;
        if (jsonParam != null && !StringUtils.isEmpty(aos) && !StringUtils.isEmpty(params)) {
            String key = RSA.rsaDecrypt(aos, "自定義的私鑰");
            if (StringUtils.isBlank(key)) {
                return null;
            }
            try {
                param = AES256.decrypt(params, key);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (StringUtils.isBlank(param)) {
                return null;
            }
        }
        if (StringUtils.isBlank(param)) {
            return null;
        }
        return JSONObject.parseObject(param);
    }
}

思路都在代碼中備注了,就是在過濾器中,一層層解析,比如token等,然后再分別解析兩種請(qǐng)求的參數(shù),放入params里,其中用到的兩個(gè)工具類如下

JSONUtil

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.MissingServletRequestParameterException;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
public class JSONUtil {
    public static JSONObject getJSONParam(HttpServletRequest request){
        Map<String, String[]> parameterMap = request.getParameterMap();
        JSONObject returnObject = new JSONObject();
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            String value = "";
            String[] values = entry.getValue();
            if (values != null){
                for (String s : values) {
                    value = s + ",";
                }
                value = value.substring(0, value.length() - 1);
            }
            returnObject.put(entry.getKey(), value);
        }
        return returnObject;
    }
    public static<T> T getParam(JSONObject param, Class<T> tClass, String key){
        if (param == null) {
            return null;
        }
        return param.getObject(key, tClass);
    }
    public static<T> T getParamRequired(JSONObject param, Class<T> tClass, String key){
        if (param == null) {
            throw new RuntimeException(getErrMsg(key));
        }
        T object = param.getObject(key, tClass);
        if (object == null){
            throw new RuntimeException(getErrMsg(key));
        }
        return object;
    }
    private static String getErrMsg(String key) {
        return "參數(shù)" + key + "必填";
    }
}

RequestBodyUtil

import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
/**
 * 解析Body數(shù)據(jù)
 */
public class RequestBodyUtil {
    private static final int BUFFER_SIZE = 1024 * 8;
    private RequestBodyUtil(){}
    public static String read(Reader reader) throws IOException {
        StringWriter writer = new StringWriter();
        try {
            write(reader, writer);
            return writer.getBuffer().toString();
        } finally {
            writer.close();
        }
    }
    public static long write(Reader reader, Writer writer) throws IOException {
        return write(reader, writer, BUFFER_SIZE);
    }
    public static long write(Reader reader, Writer writer, int bufferSize) throws IOException {
        int read;
        long total = 0;
        char[] buf = new char[BUFFER_SIZE];
        while ((read = reader.read(buf)) != -1) {
            writer.write(buf, 0, read);
            total += read;
        }
        return total;
    }
}

最后

注冊(cè)過濾器我就不說了,SpringBoot注冊(cè)過濾器方式很多,看如何在控制器中接收參數(shù)

    @PostMapping("/test")
    public Result test(@RequestParam String params){
        System.out.println("解密后的參數(shù):" + params);
        return ResponseMsgUtil.success(params);
    }

名字只要和過濾器中自定義的Map里的Key對(duì)應(yīng),就會(huì)被拿到參數(shù)

Spring boot配置Aop獲取controller里的request中的參數(shù)及其返回值

示例:

當(dāng)前url:http://localhost:8080/CarsiLogCenter_new/idpstat.jsp?action=idp.sptopn

request.getRequestURL() http://localhost:8080/CarsiLogCenter_new/idpstat.jsp
request.getRequestURI() /CarsiLogCenter_new/idpstat.jsp
request.getContextPath()/CarsiLogCenter_new
request.getServletPath() /idpstat.jsp
request.getQueryString() action=idp.sptopn
    public static String getLastAccessUrl(HttpServletRequest request) {
        StringBuffer requestURL = request.getRequestURI();
        String queryString = request.getQueryString();
        if (queryString == null) {
            return requestURL.toString();
        }
        return requestURL + "?" + queryString;
    }

1、request.getRequestURL()

  • 返回的是完整的url,包括Http協(xié)議,端口號(hào),servlet名字和映射路徑,但它不包含請(qǐng)求參數(shù)。

2、request.getRequestURI()

  • 得到的是request URL的部分值,并且web容器沒有decode過的

3、request.getContextPath()

  • 返回 the context of the request.

4、request.getServletPath()

  • 返回調(diào)用servlet的部分url.

5、request.getQueryString()

  • 返回url路徑后面的查詢字符串

首先在你的Maven的pom文件里加入aop的依賴

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
  </dependency>

在spring boot里面一切配置都是很簡(jiǎn)單的,

下面為我所有被請(qǐng)求到的controller加上Aop的功能

看碼吧:

import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;;
@Aspect   //定義一個(gè)切面
@Configuration
public class LogRecordAspect {
private static final Logger logger = LoggerFactory.getLogger(UserInterceptor.class);
    // 定義切點(diǎn)Pointcut
    @Pointcut("execution(* com.jiaobuchong.web.*Controller.*(..))")
    public void excudeService() {
    }
    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String queryString = request.getQueryString();
        logger.info("請(qǐng)求開始, 各個(gè)參數(shù), url: {}, method: {}, uri: {}, params: {}", url, method, uri, queryString);
        // result的值就是被攔截方法的返回值
        Object result = pjp.proceed();
        Gson gson = new Gson();
        logger.info("請(qǐng)求結(jié)束,controller的返回值是 " + gson.toJson(result));
        return result;
    }
}

只要加上上面這個(gè)類,Aop就算配置好了,不信,去訪問以下你的Controller試試。對(duì)比以前配置aop的方式(xml文件),現(xiàn)在的配置都到Java代碼里來(lái)了,@Configuration這個(gè)Annotation就是JavaConfig的典型代表,Spring boot在啟動(dòng)時(shí)會(huì)會(huì)自動(dòng)去加載這些配置,實(shí)現(xiàn)相應(yīng)的配置功能。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • JAVA項(xiàng)目常用異常處理匯總

    JAVA項(xiàng)目常用異常處理匯總

    這篇文章主要介紹了JAVA項(xiàng)目常用異常處理匯總,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • java程序員必須要學(xué)會(huì)的linux命令總結(jié)(推薦)

    java程序員必須要學(xué)會(huì)的linux命令總結(jié)(推薦)

    下面小編就為大家分享一篇java程序員必須要學(xué)會(huì)的linux命令總結(jié)(推薦)。具有很好的參考價(jià)值。希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2017-11-11
  • JVM垃圾回收機(jī)制和垃圾回收器詳細(xì)解說

    JVM垃圾回收機(jī)制和垃圾回收器詳細(xì)解說

    這篇文章主要介紹了JVM垃圾回收機(jī)制和垃圾回收器,為了讓程序員更加專注于代碼的實(shí)現(xiàn),而不用過多的考慮內(nèi)存釋放的問題,所以在Java語(yǔ)言中,有了自動(dòng)的垃圾回收機(jī)制,也是我們常常提及的GC,需要的朋友可以參考下
    2022-07-07
  • java文件讀寫操作實(shí)例詳解

    java文件讀寫操作實(shí)例詳解

    java的io流讀取數(shù)據(jù)使用io流讀取文件和向文件中寫數(shù)據(jù),這篇文章主要給大家介紹了關(guān)于java文件讀寫操作的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-02-02
  • SpringBoot配置主從數(shù)據(jù)庫(kù)實(shí)現(xiàn)讀寫分離

    SpringBoot配置主從數(shù)據(jù)庫(kù)實(shí)現(xiàn)讀寫分離

    現(xiàn)在的 Web 應(yīng)用大都是讀多寫少,本文主要介紹了SpringBoot配置主從數(shù)據(jù)庫(kù)實(shí)現(xiàn)讀寫分離,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • IDEA 顯示Run Dashboard窗口的2種方式(推薦)

    IDEA 顯示Run Dashboard窗口的2種方式(推薦)

    這篇文章主要介紹了IDEA 顯示Run Dashboard窗口的2種方式,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java設(shè)計(jì)模式之橋模式(Bridge模式)介紹

    Java設(shè)計(jì)模式之橋模式(Bridge模式)介紹

    這篇文章主要介紹了Java設(shè)計(jì)模式之橋模式(Bridge模式)介紹,本文講解了為什么使用橋模式、如何實(shí)現(xiàn)橋模式、Bridge模式在EJB中的應(yīng)用等內(nèi)容,需要的朋友可以參考下
    2015-03-03
  • Java8通過Function獲取字段名的步驟

    Java8通過Function獲取字段名的步驟

    這篇文章主要介紹了Java8通過Function獲取字段名,需要的朋友可以參考下
    2020-04-04
  • Required?request?body?is?missing的問題及解決

    Required?request?body?is?missing的問題及解決

    這篇文章主要介紹了Required?request?body?is?missing的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java簡(jiǎn)單實(shí)現(xiàn)調(diào)用命令行并獲取執(zhí)行結(jié)果示例

    Java簡(jiǎn)單實(shí)現(xiàn)調(diào)用命令行并獲取執(zhí)行結(jié)果示例

    這篇文章主要介紹了Java簡(jiǎn)單實(shí)現(xiàn)調(diào)用命令行并獲取執(zhí)行結(jié)果,結(jié)合實(shí)例形式分析了Java調(diào)用ping命令并獲取執(zhí)行結(jié)果相關(guān)操作技巧,需要的朋友可以參考下
    2018-08-08

最新評(píng)論

潞城市| 鹤庆县| 柯坪县| 辽阳市| 镇安县| 大名县| 普宁市| 修武县| 桂东县| 聂荣县| 阳高县| 天镇县| 明溪县| 侯马市| 牡丹江市| 大关县| 平顶山市| 闻喜县| 白河县| 景德镇市| 广饶县| 商河县| 武乡县| 衡山县| 青海省| 永胜县| 闻喜县| 习水县| 贡嘎县| 孙吴县| 沾益县| 岗巴县| 南涧| 大余县| 景洪市| 屏山县| 沧州市| 漳州市| 鄢陵县| 缙云县| 渑池县|