文章目录
前言
提示:这里可以添加本文要记录的大概内容:
一、jwt做登录鉴权
1.1 写出jwt 生成token 的工具类
1.1.1 编写获取token工具类方法(getToken() )
思路:
一、首先考虑要接收的参数。要知道用户的ID或者用户名、角色等。因此这里把这三个属性封装到一个AuthInfo对象中。还要传入过期时间 和加密字符串信息。
@Data
public class AuthInfo {
private Long UserId;
private String userName;
private String roles;
}
public static String getToken(AuthInfo authInfo, Date expireDate, String secret){
return "";
}
二、 进入方法时,首先判断参数是否为空,这里我们可以使用谷歌的包:com.google.common.base.Preconditions;里面有对应的API可以非常方便的做验证。
代码:
//做验证
Preconditions.checkArgument(authInfo != null,"加密内容不能为null");
Preconditions.checkArgument(expireDate != null,"过期时间异常");
Preconditions.checkArgument(secret != null,"加密密码不能为null");
三、使用JWT的Api调用方法,将Header和签名等参数赋值。
Map<String, Object> map = new HashMap<>();
// 固定格式
map.put("alg", "HS256");
map.put("typ", "JWT");
String token = null;//签名
try {
token = JWT.create()
.withHeader(map)//头
// 参数
.withClaim(USER_ID,authInfo.getUserId())
.withClaim(USER_NAME,authInfo.getUserName())
.withClaim(USER_ROLES,authInfo.getRoles())
.withIssuedAt(new Date())//签名时间
.withExpiresAt(expireDate)//过期时间
.sign(Algorithm.HMAC256(secret));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (JWTCreationException e) {
e.printStackTrace();
}
四、返回token 字符串,下面是完整代码:
package com.tzw.gene.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.google.common.base.Preconditions;
import com.tzw.gene.auth.AuthInfo;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author tzw
* @version 1.0
*/
public class JwtUtil {
public static String USER_ID = "userId";
public static String USER_NAME = "userName";
public static String USER_ROLES = "roles";
/**
* 生成token
* @param authInfo
* @param expireDate
* @param secret
* @return
*/
public static String getToken(AuthInfo authInfo, Date expireDate, String secret){
Preconditions.checkArgument(authInfo != null,"加密内容不能为null");
Preconditions.checkArgument(expireDate != null,"过期时间异常");
Preconditions.checkArgument(secret != null,"加密密码不能为null");
Map<String, Object> map = new HashMap<>();
map.put("alg", "HS256");
map.put("typ", "JWT");
String token = null;//签名
try {
token = JWT.create()
.withHeader(map)//头
.withClaim(USER_ID,authInfo.getUserId())
.withClaim(USER_NAME,authInfo.getUserName())
.withClaim(USER_ROLES,authInfo.getRoles())
.withIssuedAt(new Date())//签名时间
.withExpiresAt(expireDate)//过期时间
.sign(Algorithm.HMAC256(secret));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (JWTCreationException e) {
e.printStackTrace();
}
return token;
}
/**
* 验证 token正确性 并且返回authInfo对象
* @param token
* @param secret
* @return
* @throws Exception
*/
public static AuthInfo verifyToken(String token,String secret)throws Exception{
JWTVerifier verifier = null;
try {
verifier = JWT.require(Algorithm.HMAC256(secret)).build();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
DecodedJWT jwt = null;
try {
jwt = verifier.verify(token);
}catch (Exception e){
// todo 统一异常处理
throw new RuntimeException("凭证已过期,请重新登录");
}
AuthInfo authInfo = new AuthInfo();
authInfo.setUserId(jwt.getClaim(USER_ID).asLong());
authInfo.setUserName(jwt.getClaim(USER_NAME).asString());
authInfo.setRoles(jwt.getClaim(USER_ROLES).asString());
return authInfo;
}
1.2 写出jwt 验证token 并且能够逆向转换成我们加密使用的对象(verifyToken() )
验证 token正确性 并且返回AuthInfo对象
思路:
一、同样的,我们还是先考虑参数,很明显我们需要传入token字符串和一个密文(secret)
二、然后用JWT.require(Algorithm.HMAC256(secret)).build()赋值给JWTVerifier对象,这时会验证密文的正确性,如果正确则会得到JWTVerifier对象。
三、然后再通过JWTVerifier验证token是否过期。没有过期我们再得到AuthInfo(把AuthInfo从JWTVerifier对象解析出来最后返回。)
代码如下:
/**
* 验证 token正确性 并且返回authInfo对象
* @param token
* @param secret
* @return
* @throws Exception
*/
public static AuthInfo verifyToken(String token,String secret)throws Exception{
JWTVerifier verifier = null;
try {
verifier = JWT.require(Algorithm.HMAC256(secret)).build();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
DecodedJWT jwt = null;
try {
//验证token是否过期
jwt = verifier.verify(token);
}catch (Exception e){
// todo 统一异常处理
throw new RuntimeException("凭证已过期,请重新登录");
}
//下面得到AuthInfo对象
AuthInfo authInfo = new AuthInfo();
authInfo.setUserId(jwt.getClaim(USER_ID).asLong());
authInfo.setUserName(jwt.getClaim(USER_NAME).asString());
authInfo.setRoles(jwt.getClaim(USER_ROLES).asString());
//返回authinfo对象
return authInfo;
}
写一个main方法测试
public static void main(String[] args) {
AuthInfo authInfo = new AuthInfo();
authInfo.setUserId(1L);
authInfo.setUserName("张三");
authInfo.setRoles("管理员");
String token = getToken(authInfo, new Date(), "123456");
System.out.println(token);
AuthInfo verifyToken = null;
try {
verifyToken = verifyToken(token, "123456");
} catch (Exception e) {
e.printStackTrace();
}
}
1.3 登录接口中调用JwtUtil生成token 并且返回给前端
service层代码:
package com.tzw.gene.service.impl;
import com.tzw.gene.auth.AuthInfo;
import com.tzw.gene.entity.User;
import com.tzw.gene.mapper.UserMapper;
import com.tzw.gene.resp.LoginResp;
import com.tzw.gene.resp.UserResp;
import com.tzw.gene.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tzw.gene.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
/**
* <p>
* 服务实现类
* </p>
*
* @author student_tzw
* @since 2022-09-05
*/
@Service
public class UserServiceImpl implements IUserService {
@Autowired
UserMapper mapper;
private static final String SECRET="123456";
private static final Integer EXPIRED =24*3*60*60*1000;//3天(小时为单位)
@Override
public LoginResp login(String accountId, String password) {
LoginResp loginResp = new LoginResp();
UserResp userResp = mapper.login(accountId,password);
if (userResp == null){
loginResp.setSuccess(false);
loginResp.setMsg("账号或密码不存在");
return loginResp;
}
//jwt生成token todo(已完成)
AuthInfo authInfo = new AuthInfo();
authInfo.setUserId(userResp.getId());
authInfo.setUserName(userResp.getRealName());
authInfo.setRoles("admin,user");//todo 角色没有加进来
Date date = new Date(new Date().getTime()+ EXPIRED);
String token = JwtUtil.getToken(authInfo, date, SECRET);
userResp.setToken(token);
loginResp.setData(userResp);
return loginResp;
}
}
service接口:
package com.tzw.gene.service;
import com.tzw.gene.entity.User;
import com.baomidou.mybatisplus.extension.service.IService;
import com.tzw.gene.resp.LoginResp;
/**
* <p>
* 服务类
* </p>
*
* @author student_tzw
* @since 2022-09-05
*/
public interface IUserService{
public LoginResp login(String accountId,String password);
}
entity(实体层):(含Swagger)
package com.tzw.gene.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
*
* </p>
*
* @author student_tzw
* @since 2022-09-05
*/
@Data
@TableName("tb_user")
@ApiModel(value = "User对象", description = "")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("表的字段id")//swagger
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("公司部门id ")
private String deptId;
@ApiModelProperty("用户姓名")
private String realName;
@ApiModelProperty("登录账号")
private Long accountId;
@ApiModelProperty("登录密码")
private String password;
@ApiModelProperty("邮箱地址")
private String email;
@ApiModelProperty("手机号")
private String userPhone;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("创建人")
private String createUser;
@ApiModelProperty("更新人")
private String updateUser;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("状态")
private String status;
}
mapper:
@Repository
public interface UserMapper extends BaseMapper<User> {
UserResp login(@Param("accountId") String accountId,@Param("password") String password);
}
返回对象:
package com.tzw.gene.resp;
import lombok.Data;
/**
* @author tzw
* @version 1.0
*/
@Data
public class UserResp {
private Long id;
private String realName;
private String deptId;
private String phone;
private String token;
}