在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    SpringCloud Gateway API接口安全設(shè)計(加密 、簽名、安全)

    SpringCloud Gateway API接口安全設(shè)計(加密 、簽名、安全)

    防止數(shù)據(jù)抓包竊取

    風(fēng)險簡述

    簡述:當(dāng)用戶登錄時,惡意攻擊者可以用抓包工具可以拿到用戶提交的表單信息,可以獲取用戶的賬號密碼,進而可以惡意訪問網(wǎng)站。

    RSA 非對稱加密

    RSA簡介

    RSA加密算法是一種非對稱加密算法。在公開密鑰加密和電子商業(yè)中RSA被廣泛使用。RSA是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當(dāng)時他們?nèi)硕荚?span id="tf11vwa" class="wpcom_tag_link">麻省理工學(xué)院工作。RSA就是他們?nèi)诵帐祥_頭字母拼在一起組成的。

    假如有人找到一種快速因數(shù)分解的算法的話,那么用RSA加密的信息的可靠性就肯定會極度下降。但找到這樣的算法的可能性是非常小的。今天只有短的RSA鑰匙才可能被強力方式解破。到目前為止,世界上還沒有任何可靠的攻擊RSA算法的方式。只要其鑰匙的長度足夠長,用RSA加密的信息實際上是不能被解破的。

    1983年麻省理工學(xué)院在美國為RSA算法申請了專利。這個專利2000年9月21日失效。由于該算法在申請專利前就已經(jīng)被發(fā)表了,在世界上大多數(shù)其它地區(qū)這個專利權(quán)不被承認。

    RSA應(yīng)用過程

    非對稱算法的在應(yīng)用的過程如下:

    • 接收方生成公鑰和私鑰,公鑰公開,私鑰保留;
    • 發(fā)送方將要發(fā)送的消息采用公鑰加密,得到密文,然后將密文發(fā)送給接收方;
    • 接收方收到密文后,用自己的私鑰進行解密,獲得明文。

    RSA工具類

    package com.demo.utils;import java.util.Map;@Slf4jpublic class RSAUtils { public static final String PUBLIC_KEY = “public_key”; public static final String PRIVATE_KEY = “private_key”; public static Map generateRasKey() { Map rs = new HashMap(); try { // KeyPairGenerator類用于生成公鑰和私鑰對,基于RSA算法生成對象 KeyPairGenerator keyPairGen = null; keyPairGen = KeyPairGenerator.getInstance(“RSA”); keyPairGen.initialize(1024, new SecureRandom()); // 生成一個密鑰對,保存在keyPair中 KeyPair keyPair = keyPairGen.generateKeyPair(); // 得到私鑰 公鑰 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded())); // 得到私鑰字符串 String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded()))); // 將公鑰和私鑰保存到Map rs.put(PUBLIC_KEY, publicKeyString); rs.put(PRIVATE_KEY, privateKeyString); } catch (Exception e) { log.error(“RsaUtils invoke genKeyPair failed.”, e); throw new RsaException(“RsaUtils invoke genKeyPair failed.”); } return rs; } public static String encrypt(String str, String publicKey) { try { //base64編碼的公鑰 byte[] decoded = Base64.decodeBase64(publicKey); RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(“RSA”).generatePublic(new X509EncodedKeySpec(decoded)); //RSA加密 Cipher cipher = Cipher.getInstance(“RSA”); cipher.init(Cipher.ENCRYPT_MODE, pubKey); return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8))); } catch (Exception e) { log.error(“RsaUtils invoke encrypt failed.”, e); throw new RsaException(“RsaUtils invoke encrypt failed.”); } } public static String decrypt(String str, String privateKey) { try { //64位解碼加密后的字符串 byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8)); //base64編碼的私鑰 byte[] decoded = Base64.decodeBase64(privateKey); RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(“RSA”).generatePrivate(new PKCS8EncodedKeySpec(decoded)); //RSA解密 Cipher cipher = Cipher.getInstance(“RSA”); cipher.init(Cipher.DECRYPT_MODE, priKey); return new String(cipher.doFinal(inputByte)); } catch (Exception e) { log.error(“RsaUtils invoke decrypt failed.”, e); throw new RsaException(“RsaUtils invoke decrypt failed.”); } }}

    RsaException: 是自定義異常

    @Getterpublic class RsaException extends RuntimeException { private final String message; public RsaException(String message) { this.message = message; }}

    1.2.4 UT

    package com.rosh;public class RsaTest { /** * 用測試生成的公鑰,私鑰賦值 */ private static final String PUBLIC_KEY = “MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCFtTlL61IqIGd+fRLUhJ0MjsqFXFJswCohJ45m51WvbxDPRP3gllW0WChk74D5JEOpMDSWo4C7RfoGlBRNW7kQ6qYGukYZ5jgYpzoT0+gp3on96fQXEyQJysv9xiTPIdmSXXVVj1HAOJw29RbzxIVKUSzzPXvEtXRTtCC1+wkAJQIDAQAB”; private static final String PRIVATE_KEY = “MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIW1OUvrUiogZ359EtSEnQyOyoVcUmzAKiEnjmbnVa9vEM9E/eCWVbRYKGTvgPkkQ6kwNJajgLtF+gaUFE1buRDqpga6RhnmOBinOhPT6Cneif3p9BcTJAnKy/3GJM8h2ZJddVWPUcA4nDb1FvPEhUpRLPM9e8S1dFO0ILX7CQAlAgMBAAECgYBC4amtbiKFa/wY61tV7pfYRjzLhKi+OUlZmD3E/4Z+4KGZ7DrJ8qkgMtDR3HO5LAikQrare1HTW2d7juqw32ascu+uDObf4yrYNKin+ZDLUYvIDfLhThPxnZJwQ/trdtfxO3VM//XbwZacmwYbAsYW/3QPUXwwOPAgbC2oth8kqQJBANKLyXcdjZx4cwJVl7xNeC847su8y6bPpcBASsaQloCIPiNBIg1h76dpfEGIQBYWJWbBsxtHe/MhOmz7fNFDS2sCQQCiktYZR0dZNH4eNX329LoRuBiltpr9tf36rVOlKr1GSHkLYEHF2qtyXV2mdrY8ZWpvuo3qm1oSLaqmop2rN9avAkBHk85B+IIUF77BpGeZVJzvMOO9z8lMRHuNCE5jgvQnbinxwkrZUdovh+T+QlvHJnBApslFFOBGn51FP5oHamFRAkEAmwZmPsinkrrpoKjlqz6GyCrC5hKRDWoj/IyXfKKaxpCJTH3HeoIghvfdO8Vr1X/n1Q8SESt+4mLFngznSMQAZQJBAJx07bCFYbA2IocfFV5LTEYTIiUeKdue2NP2yWqZ/+tB5H7jNwQTJmX1mn0W/sZm4+nJM7SjfETpNZhH49+rV6U=”; /** * 生成公鑰私鑰 */ @Test public void generateRsaKey() { Map map = RSAUtils.generateRasKey(); System.out.println(“隨機生成的公鑰為:” + map.get(RSAUtils.PUBLIC_KEY)); System.out.println(“隨機生成的私鑰為:” + map.get(RSAUtils.PRIVATE_KEY)); } /** * 加密: Yeidauky/iN1/whevov2+ntzXJKAp2AHfESu5ixnDqH5iB7ww+TcfqJpDfkPHfb12Y0sVXw0gBHNJ4inkh7l2/SJBze3pKQU/mg3oyDokTia3JZIs+e80/iJcSfN+yA1JaqY+eJPYiBiOGAF2S6x0ynvJg/Wj0fwp2Tq3PDzRMo= */ @Test public void testEncrypt() { JSONObject jsonObject = new JSONObject(); jsonObject.put(“username”, “rosh”); jsonObject.put(“password”, “123456”); String str = jsonObject.toJSONString(); String encrypt = RSAUtils.encrypt(str, PUBLIC_KEY); System.out.println(encrypt); } @Test public void testDecrypt() { String decrypt = RSAUtils.decrypt(“Yeidauky/iN1/whevov2+ntzXJKAp2AHfESu5ixnDqH5iB7ww+TcfqJpDfkPHfb12Y0sVXw0gBHNJ4inkh7l2/SJBze3pKQU/mg3oyDokTia3JZIs+e80/iJcSfN+yA1JaqY+eJPYiBiOGAF2S6x0ynvJg/Wj0fwp2Tq3PDzRMo=”, PRIVATE_KEY); System.out.println(decrypt); }}

    案例

    SpringCloud Gateway + SpringBoot + Nacos+redis

    前端登錄代碼

    后端把公鑰跟前端約定好:

    登錄頁面

    登錄

    賬號: 密碼:

    前端查詢代碼

    設(shè)定公鑰、token,token是登錄成功后返回的值

    查詢測試id:

    GatewayFilterConfig

    解密前端傳來的參數(shù)并修改傳參

    package com.demo.gateway.config;public class GatewayFilterConfig implements GlobalFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { //1 如果是登錄不校驗Token String requestUrl = exchange.getRequest().getPath().value(); AntPathMatcher pathMatcher = new AntPathMatcher(); if (!pathMatcher.match(“/user/login”, requestUrl)) { String token = exchange.getRequest().getHeaders().getFirst(UserConstant.TOKEN); Claims claim = TokenUtils.getClaim(token); if (StringUtils.isBlank(token) || claim == null) { return FilterUtils.invalidToken(exchange); } } //2 修改請求參數(shù),并獲取請求參數(shù) try { updateRequestParam(exchange); } catch (Exception e) { return FilterUtils.invalidUrl(exchange); } //3 獲取請求體,修改請求體 ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders()); Mono modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> { String encrypt = RSAUtils.decrypt(body, RSAConstant.PRIVATE_KEY); return Mono.just(encrypt); }); //創(chuàng)建BodyInserter修改請求體 BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class); HttpHeaders headers = new HttpHeaders(); headers.putAll(exchange.getRequest().getHeaders()); headers.remove(HttpHeaders.CONTENT_LENGTH); //創(chuàng)建CachedBodyOutputMessage并且把請求param加入 CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers); return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> { ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest()) { @Override public Flux getBody() { return outputMessage.getBody(); } }; return chain.filter(exchange.mutate().request(decorator).build()); })); } /** * 修改前端傳的參數(shù) */ private void updateRequestParam(ServerWebExchange exchange) throws NoSuchFieldException, IllegalAccessException { ServerHttpRequest request = exchange.getRequest(); URI uri = request.getURI(); String query = uri.getQuery(); if (StringUtils.isNotBlank(query) && query.contains(“param”)) { String[] split = query.split(“=”); String param = RSAUtils.decrypt(split[1], RSAConstant.PRIVATE_KEY); Field targetQuery = uri.getClass().getDeclaredField(“query”); targetQuery.setAccessible(true); targetQuery.set(uri, param); } } @Override public int getOrder() { return 80; }}

    GateWay 統(tǒng)一異常

    public abstract class AbstractExceptionHandler { protected JSONObject buildErrorMap(Throwable ex) { JSONObject json = new JSONObject(); if (ex instanceof RSAException || ex instanceof IllegalArgumentException) { json.put(“code”, HttpStatus.BAD_REQUEST.value()); if (StringUtils.isNotBlank(ex.getMessage())){ json.put(“msg”, ex.getMessage()); }else { json.put(“msg”, “無效的請求”); } } else { json.put(“code”, HttpStatus.BAD_REQUEST.value()); json.put(“msg”, “未知錯誤聯(lián)系管理員”); } return json; }}@Configurationpublic class GatewayExceptionConfig { @Primary @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public ErrorWebExceptionHandler errorWebExceptionHandler(ObjectProvider viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { GatewayExceptionHandler gatewayExceptionHandler = new GatewayExceptionHandler(); gatewayExceptionHandler.setViewResolvers(viewResolversProvider.getIfAvailable(Collections::emptyList)); gatewayExceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters()); gatewayExceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders()); return gatewayExceptionHandler; }}package com.demo.gateway.exception;import com.alibaba.fastjson.JSONObject;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;import org.springframework.http.HttpStatus;import org.springframework.http.MediaType;import org.springframework.http.codec.HttpMessageReader;import org.springframework.http.codec.HttpMessageWriter;import org.springframework.util.Assert;import org.springframework.web.reactive.function.BodyInserters;import org.springframework.web.reactive.function.server.RequestPredicates;import org.springframework.web.reactive.function.server.RouterFunctions;import org.springframework.web.reactive.function.server.ServerRequest;import org.springframework.web.reactive.function.server.ServerResponse;import org.springframework.web.reactive.result.view.ViewResolver;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;import java.util.Collections;import java.util.List;import java.util.Map;@Slf4jpublic class GatewayExceptionHandler extends AbstractExceptionHandler implements ErrorWebExceptionHandler { private List messageReaders = Collections.emptyList(); private List messageWriters = Collections.emptyList(); private List viewResolvers = Collections.emptyList(); private ThreadLocal exceptionHandlerResult = new ThreadLocal(); public void setMessageReaders(List messageReaders) { Assert.notNull(messageReaders, “‘messageReaders’ must not be null”); this.messageReaders = messageReaders; } public void setViewResolvers(List viewResolvers) { this.viewResolvers = viewResolvers; } public void setMessageWriters(List messageWriters) { Assert.notNull(messageWriters, “‘messageWriters’ must not be null”); this.messageWriters = messageWriters; } @Override public Mono handle(ServerWebExchange exchange, Throwable ex) { JSONObject errorInfo = super.buildErrorMap(ex); if (exchange.getResponse().isCommitted()) { return Mono.error(ex); } exceptionHandlerResult.set(errorInfo); ServerRequest newRequest = ServerRequest.create(exchange, this.messageReaders); return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse).route(newRequest) .switchIfEmpty(Mono.error(ex)) .flatMap(handler -> handler.handle(newRequest)) .flatMap(response -> write(exchange, response)); } protected Mono renderErrorResponse(ServerRequest request) { Map result = exceptionHandlerResult.get(); return ServerResponse.status(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(result)); } private Mono write(ServerWebExchange exchange, ServerResponse response) { exchange.getResponse().getHeaders().setContentType(response.headers().getContentType()); return response.writeTo(exchange, new ResponseContext()); } private class ResponseContext implements ServerResponse.Context { @Override public List messageWriters() { return GatewayExceptionHandler.this.messageWriters; } @Override public List viewResolvers() { return GatewayExceptionHandler.this.viewResolvers; } }}

    JAVA業(yè)務(wù)代碼

    @RestController@RequestMapping(“/user”)public class UserController { @Autowired private UserService userService; @PostMapping(“/login”) public String login(@RequestBody UserForm userForm) { return userService.login(userForm); } @GetMapping(“/detail”) public JSONObject detail(@RequestParam(“id”) Long id) { return userService.detail(id); }}@Servicepublic class UserService { private static final String USERNAME = “admin”; private static final String PASSWORD = “123456”; private static final Long USER_ID = 1L; /** * 模擬 登錄 username = admin, password =123456,user_id 1L 登錄成功 返回token */ public String login(UserForm userForm) { String username = userForm.getUsername(); String password = userForm.getPassword(); if (USERNAME.equals(username) && PASSWORD.equals(password)) { JSONObject userInfo = new JSONObject(); userInfo.put(“username”, USERNAME); userInfo.put(“password”, PASSWORD); userInfo.put(“userId”, USER_ID); return TokenUtils.createToken(userInfo.toJSONString()); } return “賬號密碼不正確”; } public JSONObject detail(Long id) { JSONObject jsonObject = new JSONObject(); jsonObject.put(“id”, id); jsonObject.put(“name”, “admin”); return jsonObject; }}

    測試

    登錄:返回token

    查詢:

    設(shè)置URL有效時長

    為了增強URL安全性,前端在header中添加時間戳。

    前端代碼

    在header中添加時間戳

    2.2 后端驗證時間戳

    private Long getDateTimestamp(HttpHeaders httpHeaders) { List list = httpHeaders.get(“timestamp”); if (CollectionUtils.isEmpty(list)) { throw new IllegalArgumentException(“拒絕服務(wù)”); } long timestamp = Long.parseLong(list.get(0)); long currentTimeMillis = System.currentTimeMillis(); //有效時長為5分鐘 if (currentTimeMillis – timestamp > 1000 * 60 * 5) { throw new IllegalArgumentException(“拒絕服務(wù)”); } return timestamp; }

    測試不傳時間戳

    確保URL唯一性

    確保URL唯一性,前端請求中增加UUID,后端存入redis,有效時長為5分鐘,5分鐘重復(fù)提交拒絕服務(wù)

    修改前端請求參數(shù)

    3.2 后端增加驗證RequestId

    private String getRequestId(HttpHeaders headers) { List list = headers.get(“requestId”); if (CollectionUtils.isEmpty(list)) { throw new IllegalArgumentException(ERROR_MESSAGE); } String requestId = list.get(0); //如果requestId存在redis中直接返回 String temp = redisTemplate.opsForValue().get(requestId); if (StringUtils.isNotBlank(temp)) { throw new IllegalArgumentException(ERROR_MESSAGE); } redisTemplate.opsForValue().set(requestId, requestId, 5, TimeUnit.MINUTES); return requestId; }

    增加簽名

    最后一步,添加簽名

    前端增加簽名

    跟前端約定好,json數(shù)據(jù)按照ASCII升序排序。

    登錄頁面:

    登錄頁面

    登錄

    賬號: 密碼:

    增強讀取Body類

    /** * @Description: * @Author: Rosh * @Date: 2021/10/27 11:03 */public class MyCachedBodyOutputMessage extends CachedBodyOutputMessage { private Map paramMap; private Long dateTimestamp; private String requestId; private String sign; public MyCachedBodyOutputMessage(ServerWebExchange exchange, HttpHeaders httpHeaders) { super(exchange, httpHeaders); } public void initial(Map paramMap, String requestId, String sign, Long dateTimestamp) { this.paramMap = paramMap; this.requestId = requestId; this.sign = sign; this.dateTimestamp = dateTimestamp; } public Map getParamMap() { return paramMap; } public Long getDateTimestamp() { return dateTimestamp; } public String getRequestId() { return requestId; } public String getSign() { return sign; }}

    4.3 修改GatewayFilterConfig

    package com.demo.gateway.config;public class GatewayFilterConfig implements GlobalFilter, Ordered { @Autowired private RedisTemplate redisTemplate; private static final String ERROR_MESSAGE = “拒絕服務(wù)”; @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { //1 獲取時間戳 Long dateTimestamp = getDateTimestamp(exchange.getRequest().getHeaders()); //2 獲取RequestId String requestId = getRequestId(exchange.getRequest().getHeaders()); //3 獲取簽名 String sign = getSign(exchange.getRequest().getHeaders()); //4 如果是登錄不校驗Token String requestUrl = exchange.getRequest().getPath().value(); AntPathMatcher pathMatcher = new AntPathMatcher(); if (!pathMatcher.match(“/user/login”, requestUrl)) { String token = exchange.getRequest().getHeaders().getFirst(UserConstant.TOKEN); Claims claim = TokenUtils.getClaim(token); if (StringUtils.isBlank(token) || claim == null) { return FilterUtils.invalidToken(exchange); } } //5 修改請求參數(shù),并獲取請求參數(shù) Map paramMap; try { paramMap = updateRequestParam(exchange); } catch (Exception e) { return FilterUtils.invalidUrl(exchange); } //6 獲取請求體,修改請求體 ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders()); Mono modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> { String encrypt = RSAUtils.decrypt(body, RSAConstant.PRIVATE_KEY); JSONObject jsonObject = JSON.parseObject(encrypt); for (Map.Entry entry : jsonObject.entrySet()) { paramMap.put(entry.getKey(), entry.getValue()); } checkSign(sign, dateTimestamp, requestId, paramMap); return Mono.just(encrypt); }); //創(chuàng)建BodyInserter修改請求體 BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class); HttpHeaders headers = new HttpHeaders(); headers.putAll(exchange.getRequest().getHeaders()); headers.remove(HttpHeaders.CONTENT_LENGTH); //創(chuàng)建CachedBodyOutputMessage并且把請求param加入,初始化校驗信息 MyCachedBodyOutputMessage outputMessage = new MyCachedBodyOutputMessage(exchange, headers); outputMessage.initial(paramMap, requestId, sign, dateTimestamp); return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> { ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest()) { @Override public Flux getBody() { Flux body = outputMessage.getBody(); if (body.equals(Flux.empty())) { //驗證簽名 checkSign(outputMessage.getSign(), outputMessage.getDateTimestamp(), outputMessage.getRequestId(), outputMessage.getParamMap()); } return outputMessage.getBody(); } }; return chain.filter(exchange.mutate().request(decorator).build()); })); } public void checkSign(String sign, Long dateTimestamp, String requestId, Map paramMap) { String str = JSON.toJSONString(paramMap) + requestId + dateTimestamp; String tempSign = Md5Utils.getMD5(str.getBytes()); if (!tempSign.equals(sign)) { throw new IllegalArgumentException(ERROR_MESSAGE); } } /** * 修改前端傳的參數(shù) */ private Map updateRequestParam(ServerWebExchange exchange) throws NoSuchFieldException, IllegalAccessException { ServerHttpRequest request = exchange.getRequest(); URI uri = request.getURI(); String query = uri.getQuery(); if (StringUtils.isNotBlank(query) && query.contains(“param”)) { String[] split = query.split(“=”); String param = RSAUtils.decrypt(split[1], RSAConstant.PRIVATE_KEY); Field targetQuery = uri.getClass().getDeclaredField(“query”); targetQuery.setAccessible(true); targetQuery.set(uri, param); return getParamMap(param); } return new TreeMap(); } private Map getParamMap(String param) { Map map = new TreeMap(); String[] split = param.split(“&”); for (String str : split) { String[] params = str.split(“=”); map.put(params[0], params[1]); } return map; } private String getSign(HttpHeaders headers) { List list = headers.get(“sign”); if (CollectionUtils.isEmpty(list)) { throw new IllegalArgumentException(ERROR_MESSAGE); } return list.get(0); } private Long getDateTimestamp(HttpHeaders httpHeaders) { List list = httpHeaders.get(“timestamp”); if (CollectionUtils.isEmpty(list)) { throw new IllegalArgumentException(ERROR_MESSAGE); } long timestamp = Long.parseLong(list.get(0)); long currentTimeMillis = System.currentTimeMillis(); //有效時長為5分鐘 if (currentTimeMillis – timestamp > 1000 * 60 * 5) { throw new IllegalArgumentException(ERROR_MESSAGE); } return timestamp; } private String getRequestId(HttpHeaders headers) { List list = headers.get(“requestId”); if (CollectionUtils.isEmpty(list)) { throw new IllegalArgumentException(ERROR_MESSAGE); } String requestId = list.get(0); //如果requestId存在redis中直接返回 String temp = redisTemplate.opsForValue().get(requestId); if (StringUtils.isNotBlank(temp)) { throw new IllegalArgumentException(ERROR_MESSAGE); } redisTemplate.opsForValue().set(requestId, requestId, 5, TimeUnit.MINUTES); return requestId; } @Override public int getOrder() { return 80; }}

    測試登錄

    發(fā)現(xiàn)驗簽成功

    測試查詢

    驗簽成功

    地址

    https://gitee.com/zhurongsheng/springcloud-gateway-rsa

    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
    上一篇 2022年6月21日 06:37
    下一篇 2022年6月21日 06:37

    相關(guān)推薦

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時間:周一至周五,10:30-18:30,節(jié)假日休息