亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

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

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

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

                風(fēng)險簡述

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

                RSA 非對稱加密

                RSA簡介

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

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

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

                RSA應(yīng)用過程

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

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

                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(“隨機(jī)生成的公鑰為:” + map.get(RSAUtils.PUBLIC_KEY)); System.out.println(“隨機(jī)生成的私鑰為:” + 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有效時長

                為了增強(qiáng)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升序排序。

                登錄頁面:

                登錄頁面

                登錄

                賬號: 密碼:

                增強(qiáng)讀取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)推薦

                • 存儲過程語法(sql server存儲過程語法)

                  今天小編給各位分享存儲過程語法的知識,其中也會對sql server存儲過程語法進(jìn)行解釋,如果能碰巧解決你現(xiàn)在面臨的問題,別忘了關(guān)注本站,現(xiàn)在開始吧! oracle存儲過程基本語法…

                  2022年11月26日
                • 計算機(jī)網(wǎng)絡(luò)技術(shù)論文(計算機(jī)網(wǎng)絡(luò)技術(shù)論文七千字)

                  今天小編給各位分享計算機(jī)網(wǎng)絡(luò)技術(shù)論文的知識,其中也會對計算機(jī)網(wǎng)絡(luò)技術(shù)論文七千字進(jìn)行解釋,如果能碰巧解決你現(xiàn)在面臨的問題,別忘了關(guān)注本站,現(xiàn)在開始吧! 計算機(jī)網(wǎng)絡(luò)方面的論文3000字…

                  2022年11月26日
                • 《萬里歸途》密鑰延期至12月31日 目前票房15.65億

                  11月22日,由饒曉志執(zhí)導(dǎo),張譯、王俊凱、殷桃主演的電影《萬里歸途》宣布密鑰將延期至12月31日。 《萬里歸途》宣布密鑰將延期至12月31日。 據(jù)燈塔專業(yè)版數(shù)據(jù),該片上映54天,票…

                  2022年11月25日
                • 百度關(guān)鍵詞快速排名的4大原理解析(百度怎么刷關(guān)鍵詞)

                  近期百度公告驚雷算法2.0,升級之快還是第一次吧,看來百度對于刷點(diǎn)擊行為是零容忍了。之前尹華峰SEO技術(shù)博客介紹過一篇如何使用刷點(diǎn)擊工具,其實(shí)市面上有很多這類SEO快速排名的軟件,…

                  2022年11月25日
                • 博客營銷的3大優(yōu)勢解析(博客營銷怎么做)

                  不知不覺已經(jīng)寫了24篇文章,加上這篇是第25篇了,都是自己這幾年來用過的營銷方法,如果遇到有些不懂的,我會咨詢我的朋友和同事幫忙,盡量讓每一篇有價值,哪怕是對大家有一點(diǎn)點(diǎn)幫助也行,…

                  2022年11月25日
                • 2022全球最常用密碼名單:password成全球最常用密碼

                  11月24日消息,據(jù)IT之家報道,密碼管理工具NordPass現(xiàn)已發(fā)布2022年全球最常用的密碼名單,結(jié)果顯示用戶仍在使用眾所周知的弱密碼。統(tǒng)計數(shù)據(jù)顯示,今年全球最常見的密碼是“p…

                  2022年11月25日
                • 成都健康碼打不開顯示接口請求未知異常怎么辦(成都健康碼打不開顯示接口請求未知異常)

                  成都這幾天的疫情也是備受關(guān)注,疫情期間各地出行都是需要查看健康碼的,不過今天卻有成都的小伙伴反饋健康碼無法打開的情況。成都健康碼打不開顯示接口請求未知異常怎么辦?由于健康碼無法打開…

                  2022年11月24日
                • 銳龍97900x參數(shù)規(guī)格跑分評測 銳龍97900x屬于什么檔次

                  銳龍9 7900X是銳龍7000系列處理器中性能頂尖的型號之一,它采用了這一代標(biāo)配的zen4架構(gòu)和5nm制程工藝,那么它具體的參數(shù)跑分如何,在電腦上世紀(jì)發(fā)揮怎么樣呢,下面就來看看銳…

                  2022年11月24日
                • 前三季度,市場規(guī)模超過五萬億元 信息消費(fèi)展現(xiàn)蓬勃生機(jī)

                  家居企業(yè)個性化全屋定制系統(tǒng),備受消費(fèi)者青睞;主打?qū)I(yè)電競的新款高性能便攜式計算機(jī),銷量表現(xiàn)創(chuàng)新高;物流企業(yè)推出數(shù)智化供應(yīng)鏈興農(nóng)服務(wù)項目,助力優(yōu)質(zhì)農(nóng)產(chǎn)品出深山…… 不久前,工信部發(fā)布…

                  2022年11月24日
                • 微信微店怎么開

                  微信開店的方式有以下兩種1基于微信公眾號搭建一個“微商城”2基于微信小程序,搭建一個商城型小程序下面給你介紹一下具體的流程 1登錄微信公眾平臺,申請注冊一個微信公眾號,或者直接注冊…

                  2022年11月24日

                聯(lián)系我們

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