温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何理解Spring Cloud基于JWT创建统一的认证服务

发布时间:2021-10-12 16:21:30 来源:亿速云 阅读:170 作者:iii 栏目:编程语言

这篇文章主要讲解了“如何理解Spring Cloud基于JWT创建统一的认证服务”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解Spring Cloud基于JWT创建统一的认证服务”吧!

表结构

本教程中的案例把查数据库这一步骤省略了,大家可以自行补充,但是表的设计还是要跟大家讲解的。用户表的形式如图 1 所示。

如何理解Spring Cloud基于JWT创建统一的认证服务

相关的代码如下所示。

create table auth_user(  id int(4) not null,
  accessKey varchar(100) not null,
  secretKey varchar(100) not null,
  Primary key (id)
);Alter table auth_user comment '认证用户信息表';

这里只有简单的几个字段,若大家有别的需求可以自行去扩展。代码中的 accessKey 和 secretKey 是用户身份的标识。

JWT 工具类封装

JWT 的 GitHub 地址是:https://github.com/jwtk/jjwt,依赖配置代码如下所示。

<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.7.0</version></dependency>

用工具类进行认证主要有以下几个方法:

  • 生成 Token。

  • 检查 Token 是否合法。

  • 刷新 RSA 公钥以及私钥。


生成 Token 是在进行用户身份认证之后,通过用户的 ID 来生成一个 Token,这个 Token 采用 RSA 加密的方式进行加密,Token 的内容包括用户的 ID 和过期时间。

检查 Token 则是根据调用方带来的 Token 检查是否为合法用户,就是对 Token 进行解密操作,能解密并且在有效期内表示合法,合法则返回用户 ID。

刷新 RSA 公钥及私钥的作用是防止公钥、私钥泄露,公钥、私钥一般是写死的,不过我们可以做成配置的。集成配置管理中心后,可以对公钥、私钥进行动态修改,修改之后需要重新初始化公钥、私钥的对象信息。

获取 Token 代码如下所示。

/**
* 获取 Token
*
* @param uid 用户 ID
* @param exp 失效时间, 单位分钟
* @return*/public static String getToken(String uid, int exp) {
    Long endTime = System.currentTimeMillis() + 1000 * 60 * exp;return Jwts.builder().setSubject(uid).setExpiration(new Date(endTime))
            .signWith(SignatureAlgorithm.RS512, priKey).compact();
}

检查 Token 是否合法代码如下所示。

/**
* 检查 Token 是否合法
*
* @param token
* @return JWTResult
*/public JWTResult checkToken(String token) {try {
        Claims claims = Jwts.parser().setSigningKey(pubKey).parseClaimsJws(token).getBody();
        String sub = claims.get("sub", String.class);return new JWTResult(true, sub, "合法请求", ResponseCode.SUCCESS_CODE.getCode());
    } catch (ExpiredJwtException e) {// 在解析 JWT 字符串时, 如果'过期时间字段'已经早于当前时间,// 将会抛出 ExpiredJwtException 异常, 说明本次请求已经失效return new JWTResult(false, null, "token已过期 ", ResponseCode.TOKEN_TIMEOUT_CODE.getCode());
    } catch (SignatureException e) {// 在解析 JWT 字符串时, 如果密钥不正确, 将会解析失败, 抛出// SignatureException 异常, 说明该 JWT 字符串是伪造的return new JWTResult(false, null, "非法请求", ResponseCode.NO_AUTH_CODE.getCode());
    } catch (Exception e) {return new JWTResult(false, null, "非法请求", ResponseCode.NO_AUTH_CODE.getCode());
    }
}

完整代码如下所示。

/**
* API调用认证工具类,采用RSA加密
*/public class JWTUtils {private static RSAPrivateKey priKey;private static RSAPublicKey pubKey;private static class SingletonHolder {private static final JWTUtils INSTANCE = new JWTUtils();
    }public synchronized static JWTUtils getInstance(String modulus, String privateExponent, String publicExponent) {if (priKey == null && pubKey == null) {
            priKey = RSAUtils.getPrivateKey(modulus, privateExponent);
            pubKey = RSAUtils.getPublicKey(modulus, publicExponent);
        }return SingletonHolder.INSTANCE;
    }public synchronized static void reload(String modulus, String privateExponent, String publicExponent) {
        priKey = RSAUtils.getPrivateKey(modulus, privateExponent);
        pubKey = RSAUtils.getPublicKey(modulus, publicExponent);
    }public synchronized static JWTUtils getInstance() {if (priKey == null && pubKey == null) {
            priKey = RSAUtils.getPrivateKey(RSAUtils.modulus, RSAUtils.private_exponent);
            pubKey = RSAUtils.getPublicKey(RSAUtils.modulus, RSAUtils.public_exponent);
        }return SingletonHolder.INSTANCE;
    }/**
     * 获取Token
     *
     * @param uid 用户ID
     * @param exp 失效时间,单位分钟
     * @return */public static String getToken(String uid, int exp) {long endTime = System.currentTimeMillis() + 1000 * 60 * exp;return Jwts.builder().setSubject(uid).setExpiration(new Date(endTime))
                .signWith(SignatureAlgorithm.RS512, priKey).compact();
    }/**
     * 获取Token
     *
     * @param uid 用户ID
     * @return */public String getToken(String uid) {long endTime = System.currentTimeMillis() + 1000 * 60 * 1440;return Jwts.builder().setSubject(uid).setExpiration(new Date(endTime))
                .signWith(SignatureAlgorithm.RS512, priKey).compact();
    }/**
     * 检查Token是否合法
     *
     * @param token
     * @return JWTResult
     */public JWTResult checkToken(String token) {try {
            Claims claims = Jwts.parser().setSigningKey(pubKey).parseClaimsJws(token).getBody();
            String sub = claims.get("sub", String.class);return new JWTResult(true, sub, "合法请求", ResponseCode.SUCCESS_CODE.getCode());
        } catch (ExpiredJwtException e) {// 在解析JWT字符串时,如果‘过期时间字段’已经早于当前时间,将会抛出ExpiredJwtException异常,说明本次请求已经失效return new JWTResult(false, null, "token已过期", ResponseCode.TOKEN_TIMEOUT_CODE.getCode());
        } catch (SignatureException e) {// 在解析JWT字符串时,如果密钥不正确,将会解析失败,抛出SignatureException异常,说明该JWT字符串是伪造的return new JWTResult(false, null, "非法请求", ResponseCode.NO_AUTH_CODE.getCode());
        } catch (Exception e) {return new JWTResult(false, null, "非法请求", ResponseCode.NO_AUTH_CODE.getCode());
        }
    }public static class JWTResult {private boolean status;private String uid;private String msg;private int code;public JWTResult() {super();
        }public JWTResult(boolean status, String uid, String msg, int code) {super();this.status = status;this.uid = uid;this.msg = msg;this.code = code;
        }public int getCode() {return code;
        }public void setCode(int code) {this.code = code;
        }public String getMsg() {return msg;
        }public void setMsg(String msg) {this.msg = msg;
        }public boolean isStatus() {return status;
        }public void setStatus(boolean status) {this.status = status;
        }public String getUid() {return uid;
        }public void setUid(String uid) {this.uid = uid;
        }
    }
}

认证接口

认证接口用于调用方进行认证时,认证通过则返回一个加密的 Token 给对方,对方就可以用这个 Token 去请求别的服务了,认证获取 Token 代码如下所示。

@PostMapping("/token")public ResponseData auth(@RequestBody AuthQuery query) throws Exception {if (StringUtils.isBlank(query.getAccessKey()) || StringUtils.isBlank(query.getSecretKey())) {return ResponseData.failByParam("accessKey and secretKey not null");
    }
    User user = authService.auth(query);if (user == null) {return ResponseData.failByParam(" 认证失败 ");
    }
    JWTUtils jwt = JWTUtils.getInstance();return ResponseData.ok(jwt.getToken(user.getId().toString()));
}

认证参数代码如下所示。

/**
* API 用户认证参数类
*/public class AuthQuery {private String accessKey;private String secretKey;// get set ...}

AuthService 中的 auth 方法就是根据 accessKey 和 secretKey 判断是否有这个用户。

感谢各位的阅读,以上就是“如何理解Spring Cloud基于JWT创建统一的认证服务”的内容了,经过本文的学习后,相信大家对如何理解Spring Cloud基于JWT创建统一的认证服务这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI