소스 검색

添加 auth 模块提供 jwt 功能

reghao 4 달 전
부모
커밋
2727eb26f1

+ 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>jutil</artifactId>
+        <groupId>cn.reghao.jutil</groupId>
+        <version>1.0.0-SNAPSHOT</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/jutil/auth/JwtUtil.java

@@ -0,0 +1,146 @@
+package cn.reghao.jutil.auth;
+
+import cn.reghao.jutil.auth.model.OssPayload;
+import cn.reghao.jutil.auth.model.RefreshPayload;
+import cn.reghao.jutil.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/jutil/auth/model/JwtPayload.java

@@ -0,0 +1,47 @@
+package cn.reghao.jutil.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;
+    }
+}

+ 1 - 1
jdk/src/main/java/cn/reghao/jutil/jdk/model/jwt/OssPayload.java → auth/src/main/java/cn/reghao/jutil/auth/model/OssPayload.java

@@ -1,4 +1,4 @@
-package cn.reghao.jutil.jdk.model.jwt;
+package cn.reghao.jutil.auth.model;
 
 import java.io.Serializable;
 

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

@@ -0,0 +1,32 @@
+package cn.reghao.jutil.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;
+    }
+}

+ 0 - 48
jdk/src/main/java/cn/reghao/jutil/jdk/model/jwt/JwtPayload.java

@@ -1,48 +0,0 @@
-package cn.reghao.jutil.jdk.model.jwt;
-
-/**
- * @author reghao
- * @date 2021-07-26 09:58:45
- */
-public class JwtPayload {
-    private final Integer loginType;
-    private final Integer plat;
-    private final String userId;
-    private final String roles;
-    // 在何时过期
-    private final Long expireAt;
-    private final String signKey;
-
-    public JwtPayload(Integer loginType, Integer plat, String userId, String roles, long expireAt, String signKey) {
-        this.loginType = loginType;
-        this.plat = plat;
-        this.userId = userId;
-        this.roles = roles;
-        this.expireAt = expireAt;
-        this.signKey = signKey;
-    }
-
-    public Integer getLoginType() {
-        return loginType;
-    }
-
-    public Integer getPlat() {
-        return plat;
-    }
-
-    public String getUserId() {
-        return userId;
-    }
-
-    public String getRoles() {
-        return roles;
-    }
-
-    public Long getExpireAt() {
-        return expireAt;
-    }
-
-    public String getSignKey() {
-        return signKey;
-    }
-}

+ 1 - 0
pom.xml

@@ -12,6 +12,7 @@
         <module>jdk</module>
         <module>tool</module>
         <module>web</module>
+        <module>auth</module>
     </modules>
 
     <properties>

+ 0 - 6
tool/pom.xml

@@ -46,12 +46,6 @@
             <version>1.0.3</version>
         </dependency>
 
-        <dependency>
-            <groupId>io.jsonwebtoken</groupId>
-            <artifactId>jjwt-api</artifactId>
-            <version>0.12.6</version>
-        </dependency>
-
         <dependency>
             <groupId>org.sejda.imageio</groupId>
             <artifactId>webp-imageio</artifactId>

+ 0 - 57
tool/src/main/java/cn/reghao/jutil/tool/jwt/Jwt.java

@@ -1,57 +0,0 @@
-package cn.reghao.jutil.tool.jwt;
-
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.JwtParser;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
-
-import java.util.Date;
-
-/**
- * JWT 令牌
- *
- * @author reghao
- * @date 2019-11-17 23:10:58
- */
-public class Jwt {
-    public static final String JWT_PREFIX = "Bearer ";
-    public static final String AUTH_HEADER = "Authorization";
-
-    /**
-     * 生成一个 token
-     *
-     * @param
-     * @return
-     * @date 2019-11-21 下午4:39
-     */
-    public static String create(JwtPayload payload) {
-        return Jwts.builder()
-                .claim("loginType", payload.getLoginType())
-                .claim("plat", payload.getPlat())
-                .claim("authorities", payload.getRoles())
-                .setSubject(payload.getUserId())
-                .setExpiration(new Date(payload.getExpireAt()))
-                .signWith(SignatureAlgorithm.HS256, payload.getSignKey())
-                .compact();
-    }
-
-    /**
-     * 解析 token,过期的 token 会抛出 ExpiredJwtException 异常
-     *
-     * @param
-     * @return
-     * @date 2021-07-27 下午2:37
-     */
-    public static JwtPayload parse(String token, String signKey) {
-        JwtParser jwtParser = Jwts.parser().setSigningKey(signKey).build();
-        Claims claims = (Claims) jwtParser.parse(token);
-        //Claims claims0 = Jwts.parser().setSigningKey(signKey).parseClaimsJws(token).getBody();
-
-        String username = claims.getSubject();
-        String roles = (String) claims.get("authorities");
-        Integer loginType = (Integer) claims.get("loginType");
-        Integer plat = (Integer) claims.get("plat");
-        Date expiration = claims.getExpiration();
-        return new JwtPayload(loginType, plat, username, roles, expiration.getTime(), signKey);
-    }
-}

+ 0 - 48
tool/src/main/java/cn/reghao/jutil/tool/jwt/JwtPayload.java

@@ -1,48 +0,0 @@
-package cn.reghao.jutil.tool.jwt;
-
-/**
- * @author reghao
- * @date 2021-07-26 09:58:45
- */
-public class JwtPayload {
-    private final Integer loginType;
-    private final Integer plat;
-    private final String userId;
-    private final String roles;
-    // 在何时过期
-    private final Long expireAt;
-    private final String signKey;
-
-    public JwtPayload(Integer loginType, Integer plat, String userId, String roles, long expireAt, String signKey) {
-        this.loginType = loginType;
-        this.plat = plat;
-        this.userId = userId;
-        this.roles = roles;
-        this.expireAt = expireAt;
-        this.signKey = signKey;
-    }
-
-    public Integer getLoginType() {
-        return loginType;
-    }
-
-    public Integer getPlat() {
-        return plat;
-    }
-
-    public String getUserId() {
-        return userId;
-    }
-
-    public String getRoles() {
-        return roles;
-    }
-
-    public Long getExpireAt() {
-        return expireAt;
-    }
-
-    public String getSignKey() {
-        return signKey;
-    }
-}

+ 0 - 27
web/pom.xml

@@ -58,32 +58,5 @@
             <artifactId>guava</artifactId>
             <version>28.0-jre</version>
         </dependency>
-
-        <dependency>
-            <groupId>io.jsonwebtoken</groupId>
-            <artifactId>jjwt</artifactId>
-            <version>0.9.1</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>