跨域身份验证解决方案--JWT之封装一个工具类

简介

上篇文章讲了下 JWT 的简单使用,了解了如何创建及解析 token,这篇文章说下如何封装一个 JWT 工具类及如何在项目中去使用它做用户的鉴权。

一、JWT工具类

  • 在项目中创建 JwtUtils 工具类,加上 @Component 注解将此工具类纳入spring容器中管理,@Getter@Setter 简化代码。
@Component
@Getter
@Setter
@ConfigurationProperties("jwt.config")
public class JwtUtils {
    //签名私钥
    private String key;
    //签名的失效时间
    private Long ttl;

    /**
     * 设置认证token
     * id:登录用户id
     * subject:登录用户名
     * map:自定义的数据
     */
    public String createJwt(String id, String name, Map<String,Object> map) {
        //1.设置失效时间(毫秒)
        long now = System.currentTimeMillis();
        long exp = now + ttl;
        //2.创建jwtBuilder
        JwtBuilder jwtBuilder = Jwts.builder().setId(id).setSubject(name)
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, key);
        //3.根据map设置claims
        for(Map.Entry<String,Object> entry : map.entrySet()) {
            jwtBuilder.claim(entry.getKey(),entry.getValue());
        }
        //4.设置token过期时间
        jwtBuilder.setExpiration(new Date(exp));
        //5.创建token
        String token = jwtBuilder.compact();
        return token;
    }


    /**
     * 解析token字符串获取clamis
     */
    public Claims parseJwt(String token) {
        Claims claims = null;
        try{
            claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
        }catch (Exception e){
            e.printStackTrace();
        }
        return claims;
    }

}
  • 修改项目的 application.yml, 添加配置
#JWT配置
jwt:
 config:
    key: jwt-key  #token私匙,自定义就可以 
    ttl: 360000  #token过期时间,单位毫秒,这里是6分钟

用户登录接口

  • 定义返回码枚举类
/** 公共的返回码 返回码code: 成功:10000 失败:10001 未登录:10002 未授权:10003 抛出异常:99999 */
public enum ResultCode {
  SUCCESS(true, 10000, "操作成功!"),
  // ---系统错误返回码-----
  FAIL(false, 10001, "操作失败"),
  UNAUTHENTICATED(false, 10002, "您还未登录"),
  UNAUTHORISE(false, 10003, "权限不足"),
  SERVER_ERROR(false, 99999, "抱歉,系统繁忙,请稍后重试!"),

  // ---用户操作返回码  2xxxx----
  MOBILEORPASSWORDERROR(false, 20001, "用户名或密码错误");

  // ---企业操作返回码  3xxxx----
  // ---权限操作返回码----
  // ---其他操作返回码----

  // 操作是否成功
  boolean success;
  // 操作代码
  int code;
  // 提示信息
  String message;

  ResultCode(boolean success, int code, String message) {
    this.success = success;
    this.code = code;
    this.message = message;
  }

  public boolean getSuccess() {
    return success;
  }

  public int getCode() {
    return code;
  }

  public String getMessage() {
    return message;
  }
}
  • 定义返回体
/**
 * 数据响应对象 { success :是否成功 code :返回码 message :返回信息 data :返回数据 
 */
@Data
@NoArgsConstructor
public class Result {

  private boolean success; // 是否成功
  private Integer code; //  返回码
  private String message; // 返回信息
  private Object data; //  返回数据

  public Result(ResultCode code) {
    this.success = code.success;
    this.code = code.code;
    this.message = code.message;
  }

  public Result(ResultCode code, Object data) {
    this.success = code.success;
    this.code = code.code;
    this.message = code.message;
    this.data = data;
  }

  public Result(Integer code, String message, boolean success) {
    this.code = code;
    this.message = message;
    this.success = success;
  }

  public static Result SUCCESS() {
    return new Result(ResultCode.SUCCESS);
  }

  public static Result ERROR() {
    return new Result(ResultCode.SERVER_ERROR);
  }

  public static Result FAIL() {
    return new Result(ResultCode.FAIL);
  }
}
  • 定义用户登录接口
@RestController
public class UserController {

  @Autowired private JwtUtils jwtUtils;

  @Autowired private UserService userService;

  /**   * 用户登录   * 1.通过service根据mobile查询用户   * 2.比较password   * 3.生成jwt信息   *    */
  @PostMapping(value = "/login")
  public Result login(@RequestBody Map<String, String> loginMap) {
    String mobile = loginMap.get("mobile");
    String password = loginMap.get("password");

    // 查询用户
    User user = userService.findByMobile(mobile);
    // 登录失败
    if (user == null || !user.getPassword().equals(password)) {
      return new Result(ResultCode.MOBILEORPASSWORDERROR);;
    } else {
      // 登录成功
      Map<String, Object> map = new HashMap<>(16);
      map.put("companyId", user.getCompanyId());
      map.put("companyName", user.getCompanyName());
      //登录成功,签发token
      String token = jwtUtils.createJwt(user.getId(), user.getUsername(), map);
      return new Result(ResultCode.SUCCESS,token);
    }
  }
}

三、用户信息鉴权

用户登录成功之后,会发送一个新的请求到服务端,获取用户的详细信息。获取用户信息的过程中必须登录才能,否则不能获取。
前后端约定:前端请求微服务时需要添加头信息Authorization ,内容为Bearer+空格+token

  • 定义用户信息响应体
@Setter
@Getter
public class ProfileResult {
    private String mobile;
    private String username;
    private String company;
    private Map<String,Object> roles = new HashMap<>(16);

    public ProfileResult(User user) {
        this.mobile = user.getMobile();
        this.username = user.getUsername();
        this.company = user.getCompanyName();
		//角色数据
        Set<Role> roles = user.getRoles();
        Set<String> menus = new HashSet<>();
        Set<String> points = new HashSet<>();
        Set<String> apis = new HashSet<>();
        for (Role role : roles) {
            Set<Permission> perms = role.getPermissions();
            for (Permission perm : perms) {
                String code = perm.getCode();
                if(perm.getType() == 1) {
                    menus.add(code);
                }else if(perm.getType() == 2) {
                    points.add(code);
                }else {
                    apis.add(code);
                }
            }
        }

        this.roles.put("menus",menus);
        this.roles.put("points",points);
        this.roles.put("apis",apis);
    }
}
  • 用户信息鉴权接口,获取用户信息
/**
     * 用户登录成功之后,获取用户信息
     *      1.获取用户id
     *      2.根据用户id查询用户
     *      3.构建返回值对象
     *      4.响应
     */
    @PostMapping(value="/profile")
    public Result profile(HttpServletRequest request) throws Exception {

        /**
         * 从请求头信息中获取token数据
         *   1.获取请求头信息:名称=Authorization
         *   2.替换Bearer+空格
         *   3.解析token
         *   4.获取clamis
         */
        //1.获取请求头信息:名称=Authorization
        String authorization = request.getHeader("Authorization");
        if(StringUtils.isEmpty(authorization)) {
            throw new CommonException(ResultCode.UNAUTHENTICATED);
        }
        //2.替换Bearer+空格
        String token = authorization.replace("Bearer ","");
        //3.解析token
        Claims claims = jwtUtils.parseJwt(token);
        String userid = claims.getId();
        //查询用户
        User user = userService.findById(userid);
        //构造用户信息响应体数据
        ProfileResult result = new ProfileResult(user);
        return new Result(ResultCode.SUCCESS,result);
    }
发布了35 篇原创文章 · 获赞 52 · 访问量 1287

猜你喜欢

转载自blog.csdn.net/weixin_40242806/article/details/104458130
今日推荐