0
点赞
收藏
分享

微信扫一扫

[基础] 003 使用github提交作业

全栈学习笔记 2024-11-18 阅读 9

杂七杂八之基于JSON Web Token (JWT) 进行API认证和鉴权(Java版)

在现代Web应用和API开发中,JSON Web Token (JWT) 是一种广泛使用的认证和鉴权机制。JWT不仅简化了认证流程,还提供了安全的令牌传递方式,使得跨域认证变得更加容易。本文将详细介绍如何使用JWT进行API认证和鉴权,并提供一个简单的示例。

什么是JSON Web Token (JWT)?

JSON Web Token (JWT) 是一种开放标准 (RFC 7519),用于在网络应用之间安全地传输信息。JWT是一个紧凑的、URL安全的字符串,可以包含声明(claims),这些声明用于传输关于实体(通常是用户)的信息。JWT通常由三部分组成:

  1. Header:包含令牌的类型(即JWT)和所使用的签名算法(如HMAC SHA256或RSA)。
  2. Payload:包含声明,即关于实体的信息。声明可以分为注册声明、公有声明和私有声明。
  3. Signature:用于验证消息的完整性和确保消息来自可信方。
    一个典型的JWT可能如下所示:

JWT的工作原理

  1. 生成JWT:
    ● 用户通过用户名和密码进行登录。
    ● 服务器验证用户身份后,生成一个JWT。
    ● 服务器将JWT返回给客户端。
  2. 使用JWT:
    ● 客户端在每次请求中将JWT放在请求头的Authorization字段中,格式为Bearer 。
    ● 服务器接收到请求后,解析JWT并验证其签名。
    ● 服务器根据JWT中的信息进行鉴权,决定是否允许请求。

使用JWT进行API认证和鉴权

第一步:我们首先使用maven引入相关包

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

第二步:我们编写类AuthService,目的是生成对应的token信息

/**
 * @author Sam Zhang
 * @date 2024-11-09 08:54:54
 * @since 0.0.1
 * 注释:登录用户生成token信息
 */
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class AuthService {
    private static final String SECRET_KEY = "analysis_service";
    private static final long EXPIRATION_TIME = 86400000; // 1 day in milliseconds:86400000

    /***
     * @author Sam Zhang
     * @date 2024/11/9 9:00
     * @Description: 验证用户名密码,并且进行token生成
     * @param: username:目前写死用户名密码
     * @param: password:目前写死用户名密码
     * @return * @return java.lang.String
    */
    public String login(String username, String password) {
        // 这里验证用户名和密码
        // 验证成功后生成Token
        if(username.equals("authUser") && password.equals("authPasswd")){
            return generateToken(username);
        }else{
            return "username or password is incorrect";
        }
    }

    /**
     * @author Sam Zhang
     * @date 2024/11/9 9:04
     * @Description: 生成token
     * @param: username:通过用户名生成token
     * @return * @return java.lang.String
    */
    private String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }
}

第三步:我们编写类TokenService,对生成的token进行后续校验使用

/**
 * @author Sam Zhang
 * @date 2024-11-09 09:03:49
 * @since 0.0.1
 * 注释:验证Token的合法性
 */
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

public class TokenService {

    private static final String SECRET_KEY = "analysis_service";

    /***
     * @author Sam Zhang
     * @date 2024/11/9 9:16
     * @Description: 检查token是否还有效
     * @param: token:获取的token值
     * @return * @return boolean
    */
    public boolean isTokenValid(String token) {

        if (token != null && token.startsWith("Bearer:[\"")) {

            token = token.substring(9,token.length()-2);
            try {
                // 解析Token并验证
                Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
                return true; // 验证通过
            } catch (Exception e) {
                return false; // 验证失败
            }
        }else {
            return false; // 验证失败
        }
    }

    public String getUsernameFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
        return claims.getSubject();
    }
}

第四步:对外暴露接口,我们使用SpringBoot框架进行实现,在controller层新建类AuthService,我们提供如下对外接口

import cn.hutool.json.JSONObject;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Sam Zhang
 * @date 2024-11-09 09:18:33
 * @since 0.0.1
 * 注释:鉴权相关服务
 */

@RestController
public class AuthService {

    @Autowired
    GenerateAuthlmpl generateAuthlmpl;

    @ApiOperation(value = "使用用户名密码进行鉴权以获得token信息", notes = "使用用户名密码进行鉴权以获得token信息")
    @ApiImplicitParams({
                       @ApiImplicitParam(name = "jsonObject", value = "后续接口调用都需要鉴权",required=true,paramType = "body")
    })
    @PostMapping(value = "/gettoken",produces = "application/json;charset=UTF-8")
    public JSONObject getToken(@RequestBody JSONObject jsonObject) {

        JSONObject result = new JSONObject();
        CheckRequestBody checkRequestBody = new CheckRequestBody();
        boolean b = checkRequestBody.checkGetToken(jsonObject);
        if(!b){
            result.append("result",GETTOKENMISSBODY);
            result.append("msg","请检查请求body是否缺少对应字段");
            return result;
        }

        //检查没有问题以后,获取对应的字段信息
        String username = jsonObject.getStr("username");
        String password = jsonObject.getStr("password");

        //数据处理后传给后端进行token生成
        LoginInfos loginInfos = new LoginInfos();
        loginInfos.setUsername(username);
        loginInfos.setPassword(password);
        result = generateAuthlmpl.generateAuth(loginInfos);

        //返回结果
        return result;
    }

}

第五步:当我们需要获取对应token以后,我们需要对后续的接口进行接口验证,我们其他接口的示例如下

import cn.hutool.json.JSONObject;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * @author Sam Zhang(27988)
 * @date 2024-11-06 10:51:40
 * @since 0.0.1
 * 注释:文件处理相关接口
 */

@RestController
public class DealWithFiles {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    ExecutorService executorService = Executors.newFixedThreadPool(1);

    @Autowired
    DownLoadLogslmpl downLoadLogslmpl;

    @ApiOperation(value = "下载日志并且进行分析", notes = "下载日志并且进行分析")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "获取的token信息",required=true,paramType = "header"),
            @ApiImplicitParam(name = "jsonObject", value = "分析接口请求内容",required=true,paramType = "body")
    })
    @PostMapping(value = "/analysis",produces = "application/json;charset=UTF-8")
    public JSONObject analysisLogs(@RequestHeader("Authorization") String authHeader, @RequestBody JSONObject jsonObject) {

        JSONObject result = new JSONObject();
        //校验消息头
        TokenService tokenService = new TokenService();
        boolean tokenValid = tokenService.isTokenValid(authHeader);
        if(!tokenValid){
            result.append("result",UNAUTH);
            result.append("msg","鉴权校验失败,请检查");
            return result;
        }
      //后续代码省略
    }
}

接口验证

鉴权接口

  1. 接口名称:/gettoken
  2. 接口方法:post
  3. 消息头:Content-Type:application/json;charset=UTF-8
  4. 编码:UTF-8
  5. 请求消息体格式:Json格式
{
    "username": "XXX",
    "password": "XXX"
}

● username:鉴权用户名,当前只有这么1个。
● password:鉴权密码,当前只有这么1个。
6. 响应消息体格式:Json格式

{
    "msg": [
        "token生成成功"
    ],
    "token": [
        "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoVXNlciIsImlhdCI6MTczMTMwMzMzMywiZXhwIjoxNzMxMzg5NzMzfQ.DlxEJjQpITT_y_5W_lZS67hVJ1PTHQdMI7De1mQKH04"
    ],
    "result": [
        100
    ],
    "username": [
        "XXX"
    ]
}

● msg:返回的消息格式。
● token:返回的token信息。
● result:返回的结果码,100表示请求成功。
● username:对应用户鉴权。

需要被验证接口

  1. 接口名称:/analysis
  2. 接口方法:post
  3. 消息头:
    ● Content-Type:application/json;charset=UTF-8
    ● Authorization: Bearer:[“token信息”],样例:Authorization: Bearer:[“eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoVXNlciIsImlhdCI6MTczMTMwMzMzMywiZXhwIjoxNzMxMzg5NzMzfQ.DlxEJjQpITT_y_5W_lZS67hVJ1PTHQdMI7De1mQKH04”]
    ● 消息头如果验证不通过,则会有如下结果返回
{
  "msg":["鉴权校验失败,请检查"],
  "result":[104]
}

至此,我们基于JSON Web Token (JWT)的鉴权完成。

举报

相关推荐

0 条评论