Higress 之 JWT-Auth 微服务网关统一鉴权

Higress 之 JWT-Auth 微服务网关统一鉴权

概要

上编文章,应用接入了 Higress 网关
展示了 Higress --> Nacos --> demo-app --> demo-infra --> MySQL MGR
本篇,为应用接入鉴权,验证用户身份,保障资源API访问安全。

代码展示

构建文件添加

implementation 'org.bitbucket.b_c:jose4j:0.9.3'

创建 classpath privateKeyJson.json,publicKeyJson.json

运行 JWTHelper#rsaJsonWebKey 方法,对应日志生成存入 json文件

JWT 生成,登录认证方法调整

@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class JWTHelper {

    @SneakyThrows
    public static void rsaJsonWebKey() {
        RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);

        final String publicKeyJson = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.PUBLIC_ONLY);
        final String privateKeyJson = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE);

        log.info("publicKeyJson: {}", publicKeyJson);
        log.info("privateKeyJson: {}", privateKeyJson);
    }

    @SneakyThrows
    public static String generateJwt(Map<String, String> claim) {
        String keyId = "Today is Sunday.";

        File file = new ClassPathResource("privateKeyJson.json").getFile();
        String privateKeyJson = FileUtils.readFileToString(file, StandardCharsets.UTF_8);

        JwtClaims claims = new JwtClaims();
        claims.setGeneratedJwtId();
        claims.setIssuedAtToNow();

        NumericDate date = NumericDate.now();
        date.addSeconds(60 * 60 * 24 * 7);
        claims.setExpirationTime(date);
        claims.setNotBeforeMinutesInThePast(1);
        claims.setSubject("demo-login");
        claims.setAudience("all-users");
        claims.setIssuer("Jazz"); // 此处和插件配置 issuer 保持一致

        Optional.ofNullable(claim).ifPresent(v -> {
            for (Map.Entry<String, String> entry : v.entrySet()) {
                claims.setClaim(entry.getKey(), entry.getValue());
            }
        });

        JsonWebSignature jws = new JsonWebSignature();
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
        jws.setKeyIdHeaderValue(keyId);
        jws.setPayload(claims.toJson());
        PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyJson)).getPrivateKey();

        jws.setKey(privateKey);
        return jws.getCompactSerialization();
    }
}
@PostMapping("/accountLogin")
public Response accountLogin(HttpServletResponse response, @RequestBody AccountLoginQry accountLoginQry) {
    Account account = accountService.accountLogin(accountLoginQry);
    account.setMobile(DesensitizedUtil.mobilePhone(account.getMobile()));

    Map<String, String> claim = new HashMap<>();
    claim.put(Account.Fields.userName, account.getUserName());
    claim.put(Account.Fields.mobile, account.getMobile());
    response.addHeader("access_token", JWTHelper.generateJwt(claim));

    return SingleResponse.of(account);
}

新增资源服务

@RequestMapping("/test")
@RestController
public class TestController {
    @GetMapping("/hello")
    public Response hello() {
        return SingleResponse.of("资源服务测试");
    }
}
在 Higress,路由配置 新增 test 路由,并开启 JWT-Auth 插件,配置如下
consumers:
- issuer: "Jazz"
  jwks: |-
    {
      "keys": [
        {
           "kty": "RSA",
            "n": "t8SUi0gOAJYiBZ-PMY6qNUESBBCBeicfjsqq2JLNIhRTPu-_W1Wzc02wuTtjkGbvLfvAM5n0yqwY8k5z_4CyO_dcf6nLfzCVby2IPvsSTFjbiftjyOJYgdeNdGkKj3wYD1WQH_SKAlD3dCMKGCxOwNw0AM76MuhRHx1OTNYR86CG6dAJhHHkCvqtookFVXL7ecwnvpqlNf-cFJz6Ibdgf6Siz-fjGq3lMHJlE0ZF-0LxW23FGWgSmR5oqG8Zhe2zg0J5xKqQsCnaJ4CM75XWtGkZjsdgSxCXaCNuhRkPcPG_tRTWZdRBqOtJDEJuKZOuoRayt_6EDShx8TNpmlshkQ",
            "e": "AQAB"
        }
      ]
    }
  name: "consumer1"
global_auth: false
issuer 为 JWTHelper#generateJwt claims.setIssuer("Jazz")
插件配置 keys 括号内容为 publicKeyJson.json 内容
至此,访问 /test/hello 资源需要权限
通过 用户名/密码 访问 /demo/accountLogin 登录认证换取 JWT (添加在响应头)
访问 /test/hello 在 url或者header 携带JWT,即可获取资源数据
url 参数为 access_token
header 参数为 Authorization 参数值格式 Bearer JWT
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值