当前位置: 首页 > wzjs >正文

网页首页设计代码seo优化是什么职业

网页首页设计代码,seo优化是什么职业,只做公司网站方案,应用商店下载安装打开JWT概览 JWT概念 JWT是全称是JSON WEB TOKEN,是一个开放标准,用于将各方数据信息作为JSON格式进行对象传递,可以对数据进行可选的数字加密,可使用RSA或ECDSA进行公钥/私钥签名。JWT最常见的使用场景就是缓存当前用户登录信息&am…

JWT概览

JWT概念

JWT是全称是JSON WEB TOKEN,是一个开放标准,用于将各方数据信息作为JSON格式进行对象传递,可以对数据进行可选的数字加密,可使用RSAECDSA进行公钥/私钥签名。JWT最常见的使用场景就是缓存当前用户登录信息,当用户登录成功之后,拿到JWT,之后用户的每一个请求在请求头携带上Authorization字段来辨别区分请求的用户信息。且不需要额外的资源开销。

JWT组成部分

JWT通常由一个头部(Header)、一个负载(Payload)和一个签名(Signature)三部分组成,这三部分之间用点(.)分隔。所以,一个完整的JWT看起来像这样:

xxxxx.yyyyy.zzzzz

下面我们来详细解析每一部分:

头部(header)

头部用于描述令牌的元数据,通常包含令牌的类型(即JWT)和所使用的签名算法(如HMAC SHA256)。

  • typ:表示令牌的类型,JWT令牌统一写为"JWT"。
  • alg:表示签名使用的算法,例如HMAC SHA256或RSA。

头部信息会被进行Base64编码,形成JWT的第一部分。

{  "typ": "JWT",  "alg": "HS256"  
}

负载(payload)

负载包含了JWT的声明,即传递的数据,这些数据通常包括用户信息和其他相关数据。声明有三种类型:注册的声明、公共的声明和私有的声明。

  • 注册的声明:这是一组预定义的声明,它们不是强制的,但是推荐使用,以提供一组有用的、可互操作的声明。如:iat(签发时间)、exp(过期时间)、aud(接收方)、sub(用户唯一标识)、jti(JWT唯一标识)等。
  • 公共的声明:可以定义任何名称,但应避免与注册的声明名称冲突。
  • 私有的声明:是提供者和消费者之间共同定义的声明。

负载同样会被Base64编码,形成JWT的第二部分。

{  "sub": "1234567890",  "name": "John Doe",  "jti": "unique-jwt-id","admin": true  
}

签名(signature)

签名将头部和负载用指定的算法进行签名,验证JWT的真实性和完整性。当接收者收到JWT时,他们可以使用相同的算法和密钥(对于HMAC算法)或使用公钥(对于RSA或ECDSA算法)验证签名。如果两个签名匹配,那么JWT就是有效的。

签名的过程如下:

  • 先将Base64编码后的头部和负载数据用点号(.)连接起来。
  • 使用指定的签名算法(例如,HMAC SHA256、RSA、ECDSA)和密钥对连接后的字符串进行签名。
  • 将生成的签名部分进行Base64Url编码,形成JWT的第三部分。

签名部分也是经过Base64Url编码的,形成JWT的第三部分。

HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)

注意:虽然Base64Url编码不是加密方式,但它可以确保JWT的字符串格式是紧凑的,并且容易在URL、POST参数或HTTP头部中传输。

技术方案设计

单点登录(SSO)

  • 单点登录(Single Sign-On, SSO) 是一种身份认证机制,允许用户通过一次登录即可访问多个相互信任的应用系统,而无需重复输入认证信息。

双Token机制

  • AccessToken
    • 短期有效(如30分钟),用于接口访问。
    • 客户端每次请求API时携带。
    • 不持久化存储,仅通过签名验证合法性。
  • RefreshToken
    • 用于获取新的Access Token,有效期长(如3天)。
    • 仅在刷新令牌时传输,不直接访问业务API。
    • 必须持久化存储(如Redis),服务端可主动使其失效。
  • 签名算法:使用RSA非对称加密算法,减少内存占用,防止篡改,并方便后续拓展子系统。

无感刷新Token

  • 客户端将由于AccesssToken过期失败的请求存储起来,携带RefreshToken成功刷新Token后,将存储的失败请求重新发起,以此达到用户无感的体验。
  • 服务端根据RefreshToken解析出userId和deviceId后,去Redis中查询存储的RefreshToken并进行比对,成功后生成新的AT和RT并返回

多端会话管理

  • 同一账号在不同设备登录时,为每个设备生成独立的RefreshToken。
  • Redis中以 userId:deviceId为键存储RefreshToken,过期时间设置为RefreshToken的过期时间。

废弃令牌移除

  • Redis中以 blacklist:token 为键存储AccessToken黑名单,键值对的过期时间设置为AccessToken的剩余有效期。
  • 直接删除Redis中的RefreshToken。

最佳实践

总体流程

JWT工具类

// JWT工具类
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;@Component
public class JwtUtil {@Value("${jwt.secret}")private String secret;@Value("${jwt.access.expiration}")private long accessExpiration;@Value("${jwt.refresh.expiration}")private long refreshExpiration;public String generateAccessToken(String username) {return Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + accessExpiration)).signWith(SignatureAlgorithm.HS512, secret).compact();}public String generateRefreshToken(String username) {return Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + refreshExpiration)).signWith(SignatureAlgorithm.HS512, secret).compact();}public boolean validateToken(String token) {try {Jwts.parser().setSigningKey(secret).parseClaimsJws(token);return true;} catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | IllegalArgumentException e) {return false;}}public String getUsernameFromToken(String token) {return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject();}
}

Redis服务类

// Redis服务类
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;@Service
public class RedisService {private final StringRedisTemplate redisTemplate;public RedisService(StringRedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}public void saveRefreshToken(String refreshToken, String username) {redisTemplate.opsForValue().set("refresh_token:" + refreshToken, username, 7, TimeUnit.DAYS);}public boolean isRefreshTokenValid(String refreshToken) {return redisTemplate.hasKey("refresh_token:" + refreshToken);}public void deleteRefreshToken(String refreshToken) {redisTemplate.delete("refresh_token:" + refreshToken);}public void addToBlacklist(String accessToken, long expirationMs) {redisTemplate.opsForValue().set("blacklist:" + accessToken, "invalid", expirationMs, TimeUnit.MILLISECONDS);}public boolean isInBlacklist(String accessToken) {return Boolean.TRUE.equals(redisTemplate.hasKey("blacklist:" + accessToken));}
}

Filter过滤器

// JWT过滤器
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class JwtFilter extends OncePerRequestFilter {private final JwtUtil jwtUtil;private final RedisService redisService;public JwtFilter(JwtUtil jwtUtil, RedisService redisService) {this.jwtUtil = jwtUtil;this.redisService = redisService;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String token = resolveToken(request);if (token == null) {filterChain.doFilter(request, response);return;}if (redisService.isInBlacklist(token)) {sendError(response, "Token invalid");return;}if (jwtUtil.validateToken(token)) {String username = jwtUtil.getUsernameFromToken(token);UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, null);SecurityContextHolder.getContext().setAuthentication(authentication);filterChain.doFilter(request, response);} else {sendError(response, "Token expired or invalid");}}private String resolveToken(HttpServletRequest request) {String bearerToken = request.getHeader("Authorization");if (bearerToken != null && bearerToken.startsWith("Bearer ")) {return bearerToken.substring(7);}return null;}private void sendError(HttpServletResponse response, String message) throws IOException {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write(message);response.getWriter().flush();}
}

Controller类

// 控制器类
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;@RestController
public class AuthController {private final JwtUtil jwtUtil;private final RedisService redisService;public AuthController(JwtUtil jwtUtil, RedisService redisService) {this.jwtUtil = jwtUtil;this.redisService = redisService;}@PostMapping("/login")public ResponseEntity<?> login(@RequestBody LoginRequest request) {// 这里应添加用户认证逻辑(如数据库验证)String username = request.getUsername();String accessToken = jwtUtil.generateAccessToken(username);String refreshToken = jwtUtil.generateRefreshToken(username);redisService.saveRefreshToken(refreshToken, username);return ResponseEntity.ok(new TokenResponse(accessToken, refreshToken));}@PostMapping("/refresh")public ResponseEntity<?> refreshToken(@RequestBody RefreshRequest request) {String refreshToken = request.getRefreshToken();if (!redisService.isRefreshTokenValid(refreshToken)) {return ResponseEntity.status(401).body("Invalid refresh token");}String username = jwtUtil.getUsernameFromToken(refreshToken);String newAccessToken = jwtUtil.generateAccessToken(username);String newRefreshToken = jwtUtil.generateRefreshToken(username);// 替换旧refreshTokenredisService.deleteRefreshToken(refreshToken);redisService.saveRefreshToken(newRefreshToken, username);// 将旧accessToken加入黑名单(可选)// long expiration = jwtUtil.getExpirationFromToken(refreshToken).getTime() - System.currentTimeMillis();// redisService.addToBlacklist(refreshToken, expiration);return ResponseEntity.ok(new TokenResponse(newAccessToken, newRefreshToken));}// DTO类private static class LoginRequest {private String username;private String password;// getters/setters}private static class RefreshRequest {private String refreshToken;// getters/setters}private static class TokenResponse {private final String accessToken;private final String refreshToken;// constructor/getters}
}

问题解析

相比单Token的优势

  • 高安全性:用户请求仅携带过期时间较短的AccessToken,即使令牌泄露,风险时间窗口也较小;用户仅在请求刷新Token时携带RefreshToken
  • 长会话:RefreshToken一般设置较长的过期时间,只要RT不过期用户就无需重复登录

引入Redis的作用

  • 方便状态管理:如果不存在Redis,用户登出后只能等待Token过期才能被动失效,增加Token暴露风险;通过在Redis中引入黑名单blacklist,可以使得Token主动失效
  • 多端会话管理:通过以 userId:deviceId为键存储不同设备的Token,实现同用户多端登录。通过删除对应设备的键并加上黑名单,可以主动剔出对应设备
  • 分布式一致性:若使用本地内存存储 RT,在分布式多节点架构中,各节点无法共享 RT 状态,导致用户在一个节点退出后,其他节点仍认为 RT 有效。Redis作为集中式存储,确保所有服务节点访问同一份 RT 数据,状态一致。

保证Token安全性

  • 存储安全性:AT存于内存或 SessionStorage(页面关闭失效),而RT通过 HttpOnly; Secure; SameSite=Strict Cookie 存储(XSS攻击无效)。
  • 传输安全性:开启HTTPS,防止中间人攻击(篡改、伪造和窃听);AT通过 Authorization: Bearer {token} 请求头传递,避免 URL 参数(防日志泄露),而RT通过 Cookie(标记 HttpOnly; Secure)传输。
http://www.dtcms.com/wzjs/37404.html

相关文章:

  • 网站建设新手如何自己做网站如何创建自己的网站
  • 沈阳网站建设培训班百度推广开户代理商
  • 做平面设计应该在哪个网站求职百度推广网址是多少
  • 网站建设方案下载做网站的平台
  • 网站制作网站价格交换免费连接
  • 地税局网站怎么做变更关键词什么意思
  • 网站建设及政务工作自查北京seo关键词优化收费
  • 湖南株洲建设局网站国内新闻热点事件
  • 网站关键词突然搜不到百度竞价排名商业模式
  • 网站建设phpstudy网店搜索引擎优化的方法
  • 凡客建网站抖音关键词查询工具
  • wordpress 数据库修改密码优化关键词排名推广
  • 新手做自己的网站爱站网查询
  • 辅助网站怎么做的厦门网络推广外包多少钱
  • 同ip下网站sem技术培训
  • 网站开发入门书籍推荐黑帽seo
  • 代运营公司哪里有网站排名优化怎样做
  • 网站关键词怎么写职业技能培训班
  • wap端是什么网站seo是啥
  • azure网站建设重庆百度seo代理
  • 动态网站开发试题及答案武汉百度关键词推广
  • 阿里巴巴国际网站官网百度推广搜索排名
  • 深圳网站的建设线上推广渠道
  • 网站建设需求问卷seo运营推广
  • 网站编辑的栏目怎么做如何快速收录一个网站的信息
  • wordpress照片记录模板深圳网络优化seo
  • 临沂网站建设服务引擎网站推广法
  • 玄武网站建设seo就业哪家好
  • 营口东站营销网站建设如何推广公司
  • 打开网站说建设中是什么问题?外贸推广具体是做什么