基于JWT的token认证实现登录、鉴权接口

一、JWT简介

1、JWT的全称是JSON WEB TOKEN

  • 基于token进行身份验证的方案;
  • 是一个字符串,由hearder、payload、signature组成;
  • 具备安全、自包含、紧揍等特点。

2、JWT优点

  • 安全性高,防止token被伪造和篡改;
  • 自包含,减少存储的开销;
  • 跨语言,支持多种语言的实现;
  • 支持过期,发布者校验。

3、不足

  • 消息体可以被base64解密成明文;
  • 不适合存放大量信息;
  • 无法作废未过期的JWT;

二、流程图

 

 

三、具体实现

1、引入jwt的依赖

<dependency>
	<groupId>com.auth0</groupId>
	<artifactId>java-jwt</artifactId>
	<version>3.1.0</version>
</dependency>

2、JwtHelper工具类,主要用于生成和校验token

package com.mooc.house.user.utils;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Map;

import org.apache.commons.lang3.time.DateUtils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.google.common.collect.Maps;

public class JwtHelper {
  
  private static final String  SECRET = "session_secret";
  
  private static final String  ISSUER = "mooc_user";
  
  
  public static String genToken(Map<String, String> claims){
    try {
      Algorithm algorithm = Algorithm.HMAC256(SECRET);
      JWTCreator.Builder builder = JWT.create().withIssuer(ISSUER).withExpiresAt(DateUtils.addDays(new Date(), 1));
      claims.forEach((k,v) -> builder.withClaim(k, v));
      return builder.sign(algorithm).toString();
    } catch (IllegalArgumentException | UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
  }
  
  public static Map<String, String> verifyToken(String token)  {
    Algorithm algorithm = null;
    try {
      algorithm = Algorithm.HMAC256(SECRET);
    } catch (IllegalArgumentException | UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
    JWTVerifier verifier = JWT.require(algorithm).withIssuer(ISSUER).build();
    DecodedJWT jwt =  verifier.verify(token);
    Map<String, Claim> map = jwt.getClaims();
    Map<String, String> resultMap = Maps.newHashMap();
    map.forEach((k,v) -> resultMap.put(k, v.asString()));
    return resultMap;
  }

}

3、User类

package com.house.user.model;

import java.util.Date;

import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.annotation.JSONField;


public class User {
  
  private Long id;
  private String  name;
  private String  phone;
  private String  email;
  private String  aboutme;
  private String  passwd;
  private String  confirmPasswd;
  private Integer type;
  private Date    createTime;
  private Integer enable;
  
  private String  avatar;
  
  @JSONField(deserialize=false,serialize=false)
  private MultipartFile avatarFile;
  
  private String newPassword;
  
  private String key;
  
  private Long  agencyId;
  
  private String token;
  
  private String enableUrl;
  
  private String agencyName;
  
  
  public Long getId() {
    return id;
  }
  public void setId(Long id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getPhone() {
    return phone;
  }
  public void setPhone(String phone) {
    this.phone = phone;
  }
  public String getEmail() {
    return email;
  }
  public void setEmail(String email) {
    this.email = email;
  }
  public String getAboutme() {
    return aboutme;
  }
  public void setAboutme(String aboutme) {
    this.aboutme = aboutme;
  }
  public String getPasswd() {
    return passwd;
  }
  public void setPasswd(String passwd) {
    this.passwd = passwd;
  }
 
  public Integer getType() {
    return type;
  }
  public void setType(Integer type) {
    this.type = type;
  }
  public String getAgencyName() {
    return agencyName;
  }
  public void setAgencyName(String agencyName) {
    this.agencyName = agencyName;
  }
  public Date getCreateTime() {
    return createTime;
  }
  public void setCreateTime(Date createTime) {
    this.createTime = createTime;
  }
  public String getConfirmPasswd() {
    return confirmPasswd;
  }
  public void setConfirmPasswd(String confirmPasswd) {
    this.confirmPasswd = confirmPasswd;
  }
  
  
  public String getKey() {
    return key;
  }
  public void setKey(String key) {
    this.key = key;
  }
  public String getToken() {
    return token;
  }
  public void setToken(String token) {
    this.token = token;
  }
  public Integer getEnable() {
    return enable;
  }
  public void setEnable(Integer enable) {
    this.enable = enable;
  }
  
  public MultipartFile getAvatarFile() {
    return avatarFile;
  }
  public String getEnableUrl() {
    return enableUrl;
  }
  public void setEnableUrl(String enableUrl) {
    this.enableUrl = enableUrl;
  }
  public void setAvatarFile(MultipartFile avatarFile) {
    this.avatarFile = avatarFile;
  }
  public String getNewPassword() {
    return newPassword;
  }
  public String getAvatar() {
    return avatar;
  }
  public void setAvatar(String avatar) {
    this.avatar = avatar;
  }
  public void setNewPassword(String newPassword) {
    this.newPassword = newPassword;
  }
  public Long getAgencyId() {
    return agencyId;
  }
  public void setAgencyId(Long agencyId) {
    this.agencyId = agencyId;
  }

  

}

4、Controller实现,

    // 登录
    @RequestMapping("auth")
    public RestResponse<User> auth(@RequestBody User user){
        User finalUser = userService.auth(user.getEmail(),user.getPasswd());
        return RestResponse.success(finalUser);
    }
    // 鉴权
    @RequestMapping("get")
    public RestResponse<User> getUser(String token){
        User finalUser = userService.getLoginedUserByToken(token);
        return RestResponse.success(finalUser);
    }
    // 退出
    @RequestMapping("logout")
    public RestResponse<Object> logout(String token){
        userService.invalidate(token);
        return RestResponse.success();
    }

5、Service

public User auth(String email, String passwd) {
        if (StringUtils.isBlank(email) || StringUtils.isBlank(passwd)) {
            throw new UserException(UserException.Type.USER_AUTH_FAIL,"User Auth Fail");
        }
        User user = new User();
        user.setEmail(email);
        user.setPasswd(HashUtils.encryPassword(passwd));
        user.setEnable(1);
        List<User> list =  getUserByQuery(user);
        if (!list.isEmpty()) {
            User retUser = list.get(0);
            onLogin(retUser);
            return retUser;
        }
        throw new UserException(UserException.Type.USER_AUTH_FAIL,"User Auth Fail");
    }

    private void onLogin(User user) {
        String token =  JwtHelper.genToken(ImmutableMap.of("email", user.getEmail(), "name", user.getName(),"ts", Instant.now().getEpochSecond()+""));
        renewToken(token,user.getEmail());
        user.setToken(token);
    }

    private String renewToken(String token, String email) {
        redisTemplate.opsForValue().set(email, token);
        redisTemplate.expire(email, 30, TimeUnit.MINUTES);
        return token;
    }
    private User getUserByEmail(String email) {
        User user = new User();
        user.setEmail(email);
        List<User> list = getUserByQuery(user);
        if (!list.isEmpty()) {
            return list.get(0);
        }
        throw new UserException(UserException.Type.USER_NOT_FOUND,"User not found for " + email);
    }

    public User getLoginedUserByToken(String token) {
        Map<String, String> map = null;
        try {
            map = JwtHelper.verifyToken(token);
        } catch (Exception e) {
            throw new UserException(UserException.Type.USER_NOT_LOGIN,"User not login");
        }
        String email =  map.get("email");
        Long expired = redisTemplate.getExpire(email);
        if (expired > 0L) {
            renewToken(token, email);
            User user = getUserByEmail(email);
            user.setToken(token);
            return user;
        }
        throw new UserException(UserException.Type.USER_NOT_LOGIN,"user not login");
    }

    public void invalidate(String token) {
        Map<String, String> map = JwtHelper.verifyToken(token);
        redisTemplate.delete(map.get("email"));
    }

6、UserExeption

package com.house.user.exception;

public class UserException extends RuntimeException implements WithTypeException {
    private static final long serialVersionUID = 1L;
    private Type type;
    public  Type type(){
        return type;
    }
    public enum Type{
        WRONG_PAGE_NUM,LACK_PARAMTER,USER_NOT_LOGIN,USER_NOT_FOUND,USER_AUTH_FAIL;
    }

    public UserException(String message){
        super(message);
        type = Type.LACK_PARAMTER;
    }

    public UserException(Type type,String message){
        super(message);
        this.type = type;
    }
}

7、Postman测试

   测试登录,返回token

测试鉴权

使用错误的token测试:

使用正确的token测试:

测试退出:

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
基于Spring Boot、OAuth2.0和JWT Token鉴权认证开发的后台接口是一种使用现代化技术实现的身份验证和授权机制。下面是关于这种后台接口的一些说明: 首先,Spring Boot是一个基于Spring框架的快速开发框架,提供了简化的配置和自动化的特性,使开发者能够更快速高效地开发后台接口。 OAuth2.0是一种开放标准的授权协议,它允许用户授权第三方应用访问他们在资源拥有者上存储的信息,而不需要将用户名和密码提供给第三方。 JWT Token(JSON Web Token)是一种用于在网络应用间安全传递声明的一种方式。它被用作身份验证和授权的令牌,通过加密并以JSON格式存储信息,确保信息的完整性和安全性。 基于以上技术,我们可以开发出具有强大安全认证能力的后台接口。首先,用户在访问接口时,需要提供他们的身份证明,这可以是用户名和密码。接口服务器会使用OAuth2.0协议进行身份验证,并颁发JWT Token给用户。用户在未来的请求中,可以使用该Token进行身份验证,而无需每次都提供用户名和密码。 接口服务器会对JWT Token进行验证,以确保Token的完整性和有效性。如果Token失效或被伪造,访问将被拒绝。如果验证通过,接口服务器会正常处理用户的请求。 使用Spring Boot和OAuth2.0进行开发,可以方便地设置权限和角色。可以根据用户的角色和权限,限制他们对某些资源的访问。 总之,基于Spring Boot、OAuth2.0和JWT Token鉴权认证开发的后台接口提供了一种安全可靠的身份验证和授权机制,能够有效保护后台接口的安全性,防止非法访问和数据泄露。这种技术组合在开发现代化的网络应用时非常有用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值