公司电子商务网站建设策划书,网站常用特效,品牌vi设计机构,微信借口的网站怎么做#x1f631; 前言#xff1a;HTTPS 就够了吗#xff1f;
很多同学觉得#xff1a;“我上了 HTTPS#xff0c;数据就是加密传输的#xff0c;很安全。”
错#xff01; HTTPS 只能防止数据在传输链路上不被窃听#xff0c;但它防不住#xff1a;
中间人攻击#xff0… 前言HTTPS 就够了吗很多同学觉得“我上了 HTTPS数据就是加密传输的很安全。”错HTTPS 只能防止数据在传输链路上不被窃听但它防不住中间人攻击MITM如果客户端被植入根证书HTTPS 一样被抓包。重放攻击黑客截获你的请求虽然解不开但他可以把这个请求重复发送 100 次比如转账接口。参数篡改黑客修改了转账金额而服务端只认 Token不校验金额是否被改过。要达到金融级安全我们需要“三道防线”。️ 一、 架构设计三道防线我们将安全逻辑封装在一个全局 Filter 中请求到达 Controller 之前必须通关。安全防御流程图 (Mermaid):三道防线1. 携带 Token Sign Timestamp2. 防重放校验通过通过全部通过过期/重复签名错误无效 Token客户端请求API 网关 / 过滤器校验 Timestamp Nonce3. 参数签名验签 (Sign)4. OAuth2 JWT 认证业务逻辑 Controller403 Forbidden401 Unauthorized401 Unauthorized 二、 第一道防线OAuth2 JWT (身份认证)这是最基础的“门票”。我们使用 Spring Security OAuth2 Resource Server 来解析 JWT。依赖引入dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-oauth2-resource-server/artifactId/dependency配置 SecurityFilterChainConfigurationEnableWebSecuritypublicclassSecurityConfig{BeanpublicSecurityFilterChainfilterChain(HttpSecurityhttp)throwsException{http.csrf(csrf-csrf.disable()).sessionManagement(session-session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)).authorizeHttpRequests(auth-auth.requestMatchers(/api/public/**).permitAll().anyRequest().authenticated())// 启用 JWT 解析.oauth2ResourceServer(oauth2-oauth2.jwt(Customizer.withDefaults()));returnhttp.build();}}这步之后接口有了基本的“登录”功能但还不够。✍️ 三、 第二道防线参数签名 (防篡改)这是金融级安全的核心。原理客户端把所有参数按 ASCII 码排序拼接成字符串加上一个双方约定的SecretKey进行 MD5 或 SHA256 运算生成sign。服务端收到请求后用同样的逻辑算一遍。如果算出来的sign和传过来的不一样说明参数被篡改了。签名工具类 (SignatureUtils):importorg.apache.commons.codec.digest.DigestUtils;importjava.util.TreeMap;importjava.util.Map;publicclassSignatureUtils{// 双方约定的盐值绝对不能暴露privatestaticfinalStringSALTAbc123456_Financial_Secret;/** * 生成签名 * param params 所有的业务参数 timestamp nonce */publicstaticStringgenerateSign(MapString,Stringparams){// 1. 使用 TreeMap 进行 ASCII 排序TreeMapString,StringsortednewTreeMap(params);StringBuildersbnewStringBuilder();for(Map.EntryString,Stringentry:sorted.entrySet()){// 排除 sign 本身和空值if(!sign.equals(entry.getKey())entry.getValue()!null){sb.append(entry.getKey()).append().append(entry.getValue()).append();}}// 2. 拼接盐值sb.append(key).append(SALT);// 3. SHA256 摘要returnDigestUtils.sha256Hex(sb.toString()).toUpperCase();}}⏱️ 四、 第三道防线Timestamp Nonce (防重放)即使黑客拿到了合法的sign他如果把这串请求拦截下来隔了 10 分钟再发一遍怎么办我们需要“时效性”和“唯一性”校验。Timestamp请求带上时间戳。服务端判断当前时间 - 请求时间 60秒直接拒绝。Nonce随机流水号。服务端将处理过的 Nonce 存入 Redis有效期 60 秒。如果发现 Redis 里已经有这个 Nonce说明是重复请求拒绝。️ 五、 终极合体自定义安全过滤器我们将上述逻辑封装在一个 Filter 中放在 Spring Security 过滤器链的上游。ComponentpublicclassApiSecurityFilterextendsOncePerRequestFilter{AutowiredprivateStringRedisTemplateredisTemplate;OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainfilterChain)throwsServletException,IOException{// 1. 获取 Header 中的安全参数Stringsignrequest.getHeader(X-Sign);Stringtimestamprequest.getHeader(X-Timestamp);Stringnoncerequest.getHeader(X-Nonce);if(!StringUtils.hasText(sign)||!StringUtils.hasText(timestamp)){response.sendError(HttpServletResponse.SC_FORBIDDEN,缺少安全参数);return;}// 2. 防重放 - 时间校验 (限制 60 秒内有效)longreqTimeLong.parseLong(timestamp);if(System.currentTimeMillis()-reqTime60000){response.sendError(HttpServletResponse.SC_FORBIDDEN,请求已过期);return;}// 3. 防重放 - Nonce 唯一性校验 (Redis)StringnonceKeynonce:nonce;BooleanisAbsentredisTemplate.opsForValue().setIfAbsent(nonceKey,1,60,TimeUnit.SECONDS);if(Boolean.FALSE.equals(isAbsent)){response.sendError(HttpServletResponse.SC_FORBIDDEN,重复的请求);return;}// 4. 防篡改 - 验签// 这里需要包装 HttpServletRequest 以便多次读取 Body (针对 POST/JSON)// 假设我们要对 URL 参数 Header 参数进行签名校验MapString,StringparamsnewHashMap();request.getParameterMap().forEach((k,v)-params.put(k,v[0]));params.put(timestamp,timestamp);params.put(nonce,nonce);StringcalculatedSignSignatureUtils.generateSign(params);if(!calculatedSign.equals(sign)){response.sendError(HttpServletResponse.SC_UNAUTHORIZED,签名验证失败);return;}// 5. 放行给下游 (Spring Security)filterChain.doFilter(request,response);}}注意对于 POST JSON 请求你需要实现HttpServletRequestWrapper来缓存 Body 流否则 Filter 读完 Body 后Controller 就读不到了。 总结通过这一套组合拳我们实现了JWT解决了“你是谁”的问题。签名解决了“数据被改”的问题。时间戳Nonce解决了“请求被偷”的问题。这基本达到了支付宝、微信支付等开放平台的安全标准。虽然增加了一些开发复杂度但在资金安全面前这一切都是值得的。Next Step:思考一下如果你的密钥SecretKey泄露了怎么办进阶方案是引入RSA 非对称加密客户端用私钥签名服务端用公钥验签。这样即使服务端代码泄露黑客也无法伪造客户端请求