springboot+jwt做登录鉴权(附完整代码)


前言

提示:这里可以添加本文要记录的大概内容:


一、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;

}

总结

猜你喜欢

转载自blog.csdn.net/qq_45821255/article/details/126731932