没有网站能做淘宝客吗,合肥建设网官方网站,加盟代理网,网站建设完整代码简述#xff1a;
Token验证处理是指在客户端和服务端之间进行身份验证和授权的过程。在这个过程中#xff0c;客户端通常会提供一个令牌#xff08;Token#xff09;#xff0c;用于证明其合法性和权限。服务端接收到该令牌后#xff0c;需要对其进行验证#xff0c;以…简述
Token验证处理是指在客户端和服务端之间进行身份验证和授权的过程。在这个过程中客户端通常会提供一个令牌Token用于证明其合法性和权限。服务端接收到该令牌后需要对其进行验证以确定该请求是否来自合法的客户端。
JWT是一种常见的Token验证处理方式。
JWT简述
JWTJSON Web Token由三部分组成它们分别是头部Header、载荷Payload和签名Signature。每个部分都使用Base64编码进行序列化并使用点号.作为分隔符。
头部Header头部包含了关于JWT的元数据信息以及指定所使用的算法的声明。常见的算法有HMAC、RSA和ECDSA等。头部通常是一个JSON对象例如 {//alg表示所使用的算法此处为HMAC SHA-256alg: HS256,//typ表示令牌的类型此处为JWTtyp: JWT
} 载荷Payload载荷包含了一些声明claims这些声明是关于实体如用户和其他数据的陈述。载荷可以包含预定义的声明如sub主题表示主体的唯一标识、exp过期时间表示令牌的有效期、iat发布时间表示令牌的发行时间等也可以包含自定义的声明。载荷通常也是一个JSON对象例如 {sub: 1234567890,name: John Doe,iat: 1516239022
}签名Signature签名是使用指定的算法如HMAC、RSA等对头部和载荷进行签名生成的一串字符串。签名用于验证令牌的完整性和真实性以防止被篡改。签名的生成需要使用密钥秘钥服务端在验证令牌时也需要使用相同的密钥进行签名验证。JWT的三部分是通过点号.连接起来形成一个完整的令牌例如 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiAiMTIzNDU2Nzg5MCIsIm5hbWUiOiAiSm9obiBEb2UiLCAiaWF0IjogMTUxNjIzOTAyMn0
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5ctoken验证处理TokenService package com.muyuan.framework.web.service;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.muyuan.common.constant.Constants;
import com.muyuan.common.core.domain.model.LoginUser;
import com.muyuan.common.core.redis.RedisCache;
import com.muyuan.common.utils.ServletUtils;
import com.muyuan.common.utils.StringUtils;
import com.muyuan.common.utils.ip.AddressUtils;
import com.muyuan.common.utils.ip.IpUtils;
import com.muyuan.common.utils.uuid.IdUtils;
import eu.bitwalker.useragentutils.UserAgent;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;/*** token验证处理** */
Component
public class TokenService {// 令牌自定义标识Value(${token.header})private String header;// 令牌秘钥Value(${token.secret})private String secret;// 令牌有效期默认30分钟Value(${token.expireTime})private int expireTime;protected static final long MILLIS_SECOND 1000;protected static final long MILLIS_MINUTE 60 * MILLIS_SECOND;private static final Long MILLIS_MINUTE_TEN 20 * 60 * 1000L;Autowiredprivate RedisCache redisCache;/*** 获取用户身份信息** return 用户信息*/public LoginUser getLoginUser(HttpServletRequest request) {// 获取请求携带的令牌String token getToken(request);//判断一个字符串是否为非空串详见字符串工具类if (StringUtils.isNotEmpty(token)) {//Claims对象它包含了Payload部分的信息也就是我们在生成Token时添加的各种自定义属性。// 例如如果我们在生成Token时添加了用户名、角色等信息// 那么在解析Token时就可以通过claims.get(username)、claims.get(role)等方法来获取这些信息。Claims claims parseToken(token);// 解析对应的权限以及用户信息//令牌前缀//public static final String LOGIN_USER_KEY login_user_key;String uuid (String) claims.get(Constants.LOGIN_USER_KEY);String userKey getTokenKey(uuid);//redisCache.getCacheObject获得缓存的基本对象(详见spring redis 工具类)LoginUser user redisCache.getCacheObject(userKey);return user;}return null;}/*** 设置用户身份信息*/public void setLoginUser(LoginUser loginUser){//判断一个字符串是否为非空串详见字符串工具类if (StringUtils.isNotNull(loginUser) StringUtils.isNotEmpty(loginUser.getToken())){refreshToken(loginUser);}}/*** 删除用户身份信息*/public void delLoginUser(String token){//判断一个字符串是否为非空串详见字符串工具类if (StringUtils.isNotEmpty(token)){String userKey getTokenKey(token);//删除单个对象redisCache.deleteObject(userKey);}}/*** 创建令牌** param loginUser 用户信息* return 令牌*/public String createToken(LoginUser loginUser) {//IdUtils id快速生成器详见文章ID生成工具String token IdUtils.fastUUID();//登录对象类的唯一标识tokenloginUser.setToken(token);//设置用户代理信息setUserAgent(loginUser);//刷新令牌有效期refreshToken(loginUser);//claims是用于存放Payload部分的信息的Map对象它包含了我们需要在Token中添加的各种自定义属性// 例如用户ID、用户名、角色等MapString, Object claims new HashMap();//常量令牌前缀public static final String LOGIN_USER_KEY login_user_key;claims.put(Constants.LOGIN_USER_KEY, token);//存放非敏感信息claims.put(username,loginUser.getUsername());claims.put(nickName,loginUser.getUser().getNickName());claims.put(createTime,loginUser.getUser().getCreateTime());return createToken(claims);}/*** 验证令牌有效期相差不足20分钟自动刷新缓存** param loginUser* return 令牌*/public void verifyToken(LoginUser loginUser){//过期时间long expireTime loginUser.getExpireTime();//当前时间long currentTime System.currentTimeMillis();if (expireTime - currentTime MILLIS_MINUTE_TEN){refreshToken(loginUser);}}/*** 刷新令牌有效期** param loginUser 登录信息*/public void refreshToken(LoginUser loginUser){//设置登录时间loginUser.setLoginTime(System.currentTimeMillis());//设置过期时间loginUser.setExpireTime(loginUser.getLoginTime() expireTime * MILLIS_MINUTE);// 根据uuid将loginUser缓存String userKey getTokenKey(loginUser.getToken());//储存redis详见文章spring redis 工具类redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);}/*** 设置用户代理信息** param loginUser 登录信息*/public void setUserAgent(LoginUser loginUser){//User-Agent是HTTP协议中的一个头部信息通常用于标识发送HTTP请求的客户端软件或代理程序的详细信息。// 它包含了客户端软件类型、版本号、操作系统类型、语言等信息。// 在Web开发中服务器可以通过User-Agent头部信息来识别客户端的浏览器和操作系统等信息。UserAgent userAgent UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader(User-Agent));//获取ip详见文章ip获取地址类String ip IpUtils.getIpAddr(ServletUtils.getRequest());//存入以下数据loginUser.setIpaddr(ip);loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));loginUser.setBrowser(userAgent.getBrowser().getName());loginUser.setOs(userAgent.getOperatingSystem().getName());}/*** 从数据声明生成令牌** param claims 数据声明* return 令牌*/private String createToken(MapString, Object claims){String token //Jwts.builder()方法创建一个JWT Builder对象用于构建JWT Token。Jwts.builder()//调用setClaims(claims)方法设置JWT Token中的payload部分即要传递的自定义信息。//这里的claims参数是一个Map对象其中包含了需要传递的键值对信息。.setClaims(claims)//signWith(SignatureAlgorithm.HS512, secret)方法对JWT Token进行签名使用的算法是HS512密钥是secret变量.signWith(SignatureAlgorithm.HS512, secret)//compact()方法将JWT Token生成为一个字符串并将其作为方法的返回值。.compact();return token;}/*** 从令牌中获取数据声明** param token 令牌* return 数据声明*/private Claims parseToken(String token){//Jwts.parser()方法创建一个JWT Parser对象用于解析JWT Tokenreturn Jwts.parser()//setSigningKey(secret)方法设置解析Token时所需的签名密钥密钥是secret变量。.setSigningKey(secret)//parseClaimsJws(token)方法对传入的JWT Token进行解析。这里的token参数是要解析的JWT Token字符串。.parseClaimsJws(token)//getBody()方法获取解析后的Token内容返回的是一个Claims对象包含了Token中的payload部分的键值对信息。.getBody();}/*** 从令牌中获取用户名** param token 令牌* return 用户名*/public String getUsernameFromToken(String token){//parseToken(token)方法解析传入的JWT TokenClaims claims parseToken(token);return claims.getSubject();}/*** 获取请求token** param request* return token*/private String getToken(HttpServletRequest request){//获取请求头名称通常为Authorization。String token request.getHeader(header);//判断一个字符串是否为非空串详见字符串工具类//判断获取到的Token字符串是否非空并且是否以预定义的Token前缀Constants.TOKEN_PREFIX开头if (StringUtils.isNotEmpty(token) token.startsWith(Constants.TOKEN_PREFIX)){//将Token前缀替换为空字符串只保留真实的Token内容。token token.replace(Constants.TOKEN_PREFIX, );}return token;}private String getTokenKey(String uuid){//登录用户 redis key//public static final String LOGIN_TOKEN_KEY login_tokens:;return Constants.LOGIN_TOKEN_KEY uuid;}
}附加登录用户身份权限LoginUser package com.muyuan.common.core.domain.model;import java.util.Collection;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.muyuan.common.core.domain.entity.SysUser;/*** 登录用户身份权限* * */
public class LoginUser implements UserDetails
{private static final long serialVersionUID 1L;/*** 用户唯一标识*/private String token;/*** 登录时间*/private Long loginTime;/*** 过期时间*/private Long expireTime;/*** 登录IP地址*/private String ipaddr;/*** 登录地点*/private String loginLocation;/*** 浏览器类型*/private String browser;/*** 操作系统*/private String os;/*** 权限列表*/private SetString permissions;/*** 用户信息*/private SysUser user;public String getToken(){return token;}public void setToken(String token){this.token token;}public LoginUser(){}public LoginUser(SysUser user, SetString permissions){this.user user;this.permissions permissions;}JsonIgnoreOverridepublic String getPassword(){return user.getPassword();}Overridepublic String getUsername(){return user.getUserName();}/*** 账户是否未过期,过期无法验证*/JsonIgnoreOverridepublic boolean isAccountNonExpired(){return true;}/*** 指定用户是否解锁,锁定的用户无法进行身份验证* * return*/JsonIgnoreOverridepublic boolean isAccountNonLocked(){return true;}/*** 指示是否已过期的用户的凭据(密码),过期的凭据防止认证* * return*/JsonIgnoreOverridepublic boolean isCredentialsNonExpired(){return true;}/*** 是否可用 ,禁用的用户不能身份验证* * return*/JsonIgnoreOverridepublic boolean isEnabled(){return true;}public Long getLoginTime(){return loginTime;}public void setLoginTime(Long loginTime){this.loginTime loginTime;}public String getIpaddr(){return ipaddr;}public void setIpaddr(String ipaddr){this.ipaddr ipaddr;}public String getLoginLocation(){return loginLocation;}public void setLoginLocation(String loginLocation){this.loginLocation loginLocation;}public String getBrowser(){return browser;}public void setBrowser(String browser){this.browser browser;}public String getOs(){return os;}public void setOs(String os){this.os os;}public Long getExpireTime(){return expireTime;}public void setExpireTime(Long expireTime){this.expireTime expireTime;}public SetString getPermissions(){return permissions;}public void setPermissions(SetString permissions){this.permissions permissions;}public SysUser getUser(){return user;}public void setUser(SysUser user){this.user user;}Overridepublic Collection? extends GrantedAuthority getAuthorities(){return null;}
}