1.token存在的问题:
(1)生成token之后,只要项目一重新启动,所有用户将被强制下线;
(2)没办法控制token的有效时长,比如,希望token三天有效;
2.JWT:
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
JWT生成的token是无状态的,服务端不存储,即一旦生成在有效期之前一直可用,无法销毁。
如果需要刷新token有效期或者提前失效需要借助缓存、数据库或者redis来自己实现对应逻辑
3.JWT的使用:
(1)首先引入依赖:
(2)添加JWT工具类
public class JwtUtil {
//过期时间 30min
private static final int EXPIRE_TIME = 30;
//私钥
private static final String TOKEN_SECRET = "privateKey";
private static final String USER_NAME = "name";
/**
* 签发对象:这个用户的id
* 签发时间:现在
* 有效时间:30分钟
* 载荷内容:暂时设计为:这个人的名字
* 加密密钥:这个人的id加上一串字符串
* @param userId
* @param userName
* @return
*/
public static String createToken(Long userId, String userName) {
Calendar nowTime = Calendar.getInstance();
nowTime.add(Calendar.MINUTE,EXPIRE_TIME);
Date expiresDate = nowTime.getTime();
return JWT.create().withAudience(userId+"") //签发对象
.withIssuedAt(new Date()) //发行时间
.withExpiresAt(expiresDate) //有效时间
.withClaim(USER_NAME, userName) //载荷,随便写几个都可以
.sign(Algorithm.HMAC256(userId+TOKEN_SECRET)); //加密
}
/**
* 检验合法性,其中secret参数就应该传入的是用户的id
* @param token
* @throws
*/
public static boolean verifyToken(String token, String secret) {
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret+TOKEN_SECRET)).build();
verifier.verify(token);
} catch (Exception e) {
//效验失败
//自定义的一个异常
e.printStackTrace();
return false;
}
return true;
}
/**
* 获取签发对象
*/
public static String getAudience(String token) {
String audience = null;
try {
audience = JWT.decode(token).getAudience().get(0);
} catch (Exception j) {
//这里是token解析失败
j.printStackTrace();
return null;
}
return audience;
}
}
(3)添加token验证拦截器
(4)登录方法验证:
@RestController
@Api(value = "登录模块", tags = {"登录模块"})
//@Controller
加在类就表面当前类所有的方法返回的均为对象形式非视图页面
//@ResponseBody
@RequestMapping("login")
public class LoginController {
@Autowired
private UserService userService;
@ApiOperation("登录接口")
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
//@PostMapping
public RestultJson login(User user){
System.out.println("login:"+user);
if(StringUtils.isEmpty(user.getUserName()) || StringUtils.isEmpty(user.getPassword())){
return RestultJson.error("用户名和密码不允许为空");
}
User userDb = userService.selectByUserNameAndPassword(user);
/**
* 获取所有权限字符串集合
*/
String token = null;
if(userDb != null){
List<String> authList = userService.listAuthListByuserId(userDb.getId());
userDb.setAuthList(authList);
// 获取到了令牌
token = JwtUtil.createToken(userDb.getId(), userDb.getUserName());
userDb.setToken(token);
}
return RestultJson.ok(userDb);
}
当我们重启项目的时候,用户不会被受干扰;
而且token还有效时长;解决了我们自定义token所具有的问题