Prechádzať zdrojové kódy

将 jutil 项目的 auth 模块迁移到 tnb

reghao 4 mesiacov pred
rodič
commit
08a889cd37

+ 59 - 0
auth/pom.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>tnb</artifactId>
+        <groupId>cn.reghao.tnb</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>auth</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <!-- jwt 认证依赖 -->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-api</artifactId>
+            <version>0.12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-impl</artifactId>
+            <version>0.12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-gson</artifactId>
+            <version>0.12.6</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+            <version>2.3.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-impl</artifactId>
+            <version>2.3.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-core</artifactId>
+            <version>2.3.0</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+    </dependencies>
+</project>

+ 146 - 0
auth/src/main/java/cn/reghao/tnb/auth/JwtUtil.java

@@ -0,0 +1,146 @@
+package cn.reghao.tnb.auth;
+
+import cn.reghao.tnb.auth.model.OssPayload;
+import cn.reghao.tnb.auth.model.RefreshPayload;
+import cn.reghao.tnb.auth.model.JwtPayload;
+import io.jsonwebtoken.*;
+
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * JWT 令牌
+ *
+ * @author reghao
+ * @date 2025-10-25 11:10:58
+ */
+public class JwtUtil {
+    public static final String JWT_PREFIX = "Bearer ";
+    public static final String AUTH_HEADER = "Authorization";
+
+    public static String createOssToken(OssPayload ossPayload, long expireAt, String signKey) {
+        return Jwts.builder()
+                .claim("action", ossPayload.getAction())
+                .claim("channelCode", ossPayload.getChannelCode())
+                .setSubject(String.valueOf(ossPayload.getUserId()))
+                .setExpiration(new Date(expireAt))
+                .signWith(SignatureAlgorithm.HS256, signKey)
+                .compact();
+    }
+
+    public static OssPayload getOssPayload(String jwtToken, String signKey) {
+        JwtParser jwtParser = Jwts.parser().setSigningKey(signKey).build();
+        Claims claims = (Claims) jwtParser.parse(jwtToken).getPayload();
+
+        String action = (String) claims.get("action");
+        Double channelCodeD = (Double) claims.get("channelCode");
+        int channelCode = channelCodeD.intValue();
+        String userIdStr = claims.getSubject();
+        return new OssPayload(channelCode, action, Integer.parseInt(userIdStr));
+    }
+
+    /**
+     * 生成一个 token
+     *
+     * @param
+     * @return
+     * @date 2019-11-21 下午4:39
+     */
+    public static String createAccessToken(JwtPayload jwtPayload, long expireAt, String signKey) {
+        String jti = UUID.randomUUID().toString().replace("-", "");
+        return Jwts.builder()
+                .claim("plat", jwtPayload.getPlat())
+                .claim("loginId", jwtPayload.getLoginId())
+                .claim("loginType", jwtPayload.getLoginType())
+                .claim("authorities", jwtPayload.getAuthorities())
+                .setSubject(jwtPayload.getUserId()+"")
+                .setExpiration(new Date(expireAt))
+                .signWith(SignatureAlgorithm.HS256, signKey)
+                .setId(jti)
+                .compact();
+    }
+
+    public static String createAccessToken(JwtPayload jwtPayload, long expireAt, RSAPrivateKey privateKey) {
+        // 根据 org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter 中的 WELL_KNOWN_AUTHORITIES_CLAIM_NAMES 字段
+        // 将用户的 authorities 设置到 scope claim
+        // TODO authorities claim 待删除
+        String jti = UUID.randomUUID().toString().replace("-", "");
+        return Jwts.builder()
+                .claim("plat", jwtPayload.getPlat())
+                .claim("loginId", jwtPayload.getLoginId())
+                .claim("loginType", jwtPayload.getLoginType())
+                .claim("scope", jwtPayload.getAuthorities())
+                .claim("authorities", jwtPayload.getAuthorities())
+                .setSubject(jwtPayload.getUserId()+"")
+                .setExpiration(new Date(expireAt))
+                .signWith(SignatureAlgorithm.RS256, privateKey)
+                .setId(jti)
+                .compact();
+    }
+
+    /**
+     * 从 jwt token 中解析出已认证的 Authentication 对象
+     * 过期的 token 会抛出 ExpiredJwtException 异常
+     *
+     * @param
+     * @return
+     * @date 2023-02-17 17:36:34
+     */
+    public static JwtPayload getJwtPayload(String jwtToken, PublicKey publicKey) {
+        JwtParser jwtParser = Jwts.parser().verifyWith(publicKey).build();
+        Claims claims = (Claims) jwtParser.parse(jwtToken).getPayload();
+
+        Double platD = (Double) claims.get("plat");
+        String loginId = (String) claims.get("loginId");
+        Double loginTypeD = (Double) claims.get("loginType");
+        String userId = claims.getSubject();
+        // TODO userId 是系统分配且固定的,但需要检查用户的 roles 是否发生变化
+        String roles = (String) claims.get("authorities");
+        long expireAt = claims.getExpiration().getTime();
+        String jti = (String) claims.get("jti");
+        if (platD == null || loginId == null || userId == null || roles == null) {
+            return null;
+        }
+
+        int plat = platD.intValue();
+        int loginType = loginTypeD.intValue();
+        return new JwtPayload(plat, loginId, Long.parseLong(userId), loginType, roles, jti);
+    }
+
+    /**
+     * 创建刷新令牌
+     *
+     * @param
+     * @return
+     * @date 2023-02-17 15:20:33
+     */
+    public static String createRefreshToken(JwtPayload jwtPayload, long expireAt, String signKey) {
+        return Jwts.builder()
+                .claim("plat", jwtPayload.getPlat())
+                .claim("loginId", jwtPayload.getLoginId())
+                .setSubject(String.valueOf(jwtPayload.getUserId()))
+                .setExpiration(new Date(expireAt))
+                .signWith(SignatureAlgorithm.HS256, signKey)
+                .compact();
+    }
+
+    /**
+     * 解析刷新令牌
+     *
+     * @param
+     * @return
+     * @date 2023-02-17 15:22:54
+     */
+    public static RefreshPayload getRefreshPayload(String jwtToken, String signKey) {
+        JwtParser jwtParser = Jwts.parser().setSigningKey(signKey).build();
+        Claims claims = (Claims) jwtParser.parse(jwtToken).getPayload();
+
+        long userId = Long.parseLong(claims.getSubject());
+        Double platD = (Double) claims.get("plat");
+        int plat = platD.intValue();
+        String loginId = (String) claims.get("loginId");
+        return new RefreshPayload(userId, plat, loginId);
+    }
+}

+ 47 - 0
auth/src/main/java/cn/reghao/tnb/auth/model/JwtPayload.java

@@ -0,0 +1,47 @@
+package cn.reghao.tnb.auth.model;
+
+/**
+ * @author reghao
+ * @date 2025-10-24 19:58:45
+ */
+public class JwtPayload {
+    private final int plat;
+    private final String loginId;
+    private final long userId;
+    private final int loginType;
+    private final String authorities;
+    private final String jti;
+
+    public JwtPayload(int plat, String loginId, long userId, int loginType, String roles, String jti) {
+        this.plat = plat;
+        this.loginId = loginId;
+        this.userId = userId;
+        this.loginType = loginType;
+        this.authorities = roles;
+        this.jti = jti;
+    }
+
+    public Integer getPlat() {
+        return plat;
+    }
+
+    public String getLoginId() {
+        return loginId;
+    }
+
+    public long getUserId() {
+        return userId;
+    }
+
+    public Integer getLoginType() {
+        return loginType;
+    }
+
+    public String getAuthorities() {
+        return authorities;
+    }
+
+    public String getJti() {
+        return jti;
+    }
+}

+ 36 - 0
auth/src/main/java/cn/reghao/tnb/auth/model/OssPayload.java

@@ -0,0 +1,36 @@
+package cn.reghao.tnb.auth.model;
+
+import java.io.Serializable;
+
+/**
+ * @author reghao
+ * @date 2023-08-23 10:26:01
+ */
+public class OssPayload implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private int channelCode;
+    private String action;
+    private int userId;
+
+    public OssPayload() {
+    }
+
+    public OssPayload(int channelCode, String action, int userId) {
+        this.channelCode = channelCode;
+        this.action = action;
+        this.userId = userId;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public int getChannelCode() {
+        return channelCode;
+    }
+
+    public int getUserId() {
+        return userId;
+    }
+}

+ 32 - 0
auth/src/main/java/cn/reghao/tnb/auth/model/RefreshPayload.java

@@ -0,0 +1,32 @@
+package cn.reghao.tnb.auth.model;
+
+/**
+ * @author reghao
+ * @date 2023-02-17 15:24:30
+ */
+public class RefreshPayload {
+    private long userId;
+    private int plat;
+    private String loginId;
+
+    public RefreshPayload() {
+    }
+
+    public RefreshPayload(long userId, int plat, String loginId) {
+        this.userId = userId;
+        this.plat = plat;
+        this.loginId = loginId;
+    }
+
+    public long getUserId() {
+        return userId;
+    }
+
+    public int getPlat() {
+        return plat;
+    }
+
+    public String getLoginId() {
+        return loginId;
+    }
+}

+ 1 - 0
pom.xml

@@ -22,6 +22,7 @@
         <module>oss-api</module>
         <module>oss-store</module>
         <module>oss-sdk</module>
+        <module>auth</module>
     </modules>
 
     <properties>