jwt token长度_spring cloud gateway实现jwt统一认证

作者 | 坚持坚持

来源 | urlify.cn/VjIZJ3

66套java从入门到精通实战课程分享

当你的项目中服务越来越多,每个服务都有自己的监听地址而又需要把这些服务提供给各式的客户端或第三方使用,那么需要把每个服务地址都暴露出来吗?如果某个服务有多个运行实例,如果进行负载均衡?用户认证和授权需要在每个服务上都做吗,能否统一做?要解决这些问题,就需要用到Api网关,Api网关提供Api请求转发服务并可与Eureka结合实现路由转发和负载均衡,同时利用AOP特性可以实现微服务用户统一认证和授权。目前比较流行的Api网关有Zuul、springcloud gateway以及支持dotnetcore的ocelot。本文使用的是springcloud。

一,搭建springcloud gateway

1,新建一个springboot项目,引入eureka-client和stater-gateway

            org.springframework.cloud        spring-cloud-starter-gateway                org.springframework.cloud        spring-cloud-starter-netflix-eureka-client                org.springframework.boot        spring-boot-starter-test        test                                    org.junit.vintage                junit-vintage-engine                        

2,项目配置文件:Application.yml

server:  port: 8020spring:  application:    name: gateway-server  cloud:    gateway:      discovery:        locator:          enabled: true //启用网关服务发关          lower-case-service-id: true //支持小写字母的服务名称(注册到eureka的服务)ek:  username: eureka  password: 123456  eureka-url: 127.0.0.1  eureka-port: 8765eureka:  client:    service-url:      defaultZone:        http://${ek.username}:${ek.password}@${ek.eureka-url}:${ek.eureka-port}/eureka  //Eureka注册地址  instance:    prefer-ip-address: true  //启用优先IP地址注册    instance-id: ${spring.application.name}@${spring.cloud.client.ip-address}@${server.port} //本网关注册到Eureka的实例id

3,启用项目注册到Eureka,并通过网关访问Api 

e2eb1cc4846f4866bc9bb9ab1082084e

验证Api

78dd5ab6f6a845ce8fccde06be336b38

二,DotnetCore JWT证书颁布服务

1,新建一个web api项目,Nuget添加:System.IdentityModel.Tokens.Jwt、Microsoft.IdentityModel.Tokens两个包。配置文件添加jwt配置信息。

appsetting.json 注意:Key用于jwt的签名,长度不能少于16位。可用openssl生成一个32位的密钥。

"Identity": {   "Jwt": {     "Key": "1234567890123456",     "Domain": "kingsun.mico"   } }

使用IOptions读取配置信息并写入依赖

Startup.cs

public void ConfigureServices(IServiceCollection services)    {        services.Configure(Configuration.GetSection("Identity"));        services.AddControllers();    }

2,新建一个名为Token的Api控制器并创建接口GetToken  

[Route("api/[controller]")]    [ApiController]    public class TokenController : ControllerBase    {        JwtConfig config;        public TokenController(IOptions config)        {            this.config = config.Value;        }        public class GetTokenRequest        {            [Required]            public string Name { get; set; }            [Required]            public string Password { get; set; }        }        public class GetTokenRespone        {            public int Code { get; set; }            public string Msg { get; set; }            public string Data { get; set; }        }        [HttpPost("GetToken")]        public object GetToken([FromBody] GetTokenRequest data)        {            GetTokenRespone respone = new GetTokenRespone()            {                Code = 0            };            if (!ModelState.IsValid)            {                respone.Msg = "用户名或密码不能为空";                return respone;            }            //验证密码逻辑            //....             //jwt中payload键值对内容            List claims = new List()            {                //用户名                new Claim("name",data.Name)            };            var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(config.Jwt.Key));            var creds = new SigningCredentials(key,SecurityAlgorithms.HmacSha256);            var token = new JwtSecurityToken(                 issuer: "liujb", audience: config.Jwt.Domain, claims: claims, signingCredentials: creds, expires:DateTime.Now.AddDays(1),notBefore:DateTime.Now                );            respone.Code = 1;            respone.Msg = "请求成功";            respone.Data = new JwtSecurityTokenHandler().WriteToken(token);            return respone;        }    }

3,获取jwt令牌

67c7d15c19544e91949b3b3bcc382b5e

可拿此令牌验证后内容如下:

725a5b0260684dbb874dae303a19c6b1

4,将此服务注册到Eureka后用api网关转发服务获取token:http://localhost:8020/eureka-identity/api/token/gettoken

{    "code": 1,    "msg": "请求成功",    "data": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoibGl1amIiLCJuYmYiOiIxNjAyODE3NjY1MjMwIiwiZXhwIjoiMTYwMjkwNDA2NTIzMCIsImlzcyI6ImxpdWpiIiwiYXVkIjoia2luZ3N1bi5taWNvIn0.5pIrNumEEy280-sCWp4d0K05Skc2Ptn1sK732Rw-L-A"}

三,在api网关统一做接口认证

1,在第一步建立的网关项目中maven加入java-jwt依赖

           com.auth0           java-jwt           3.11.0       

配置文件加入jwt密钥:jwt.key=1234567890123456。值与第二步的中密钥一致。

2,在该项目新建一个全局过滤器。

@Componentpublic class JwtFilter implements GlobalFilter, Ordered {    @Value("${jwt.key}")    public String jwtKey;    Logger logger=null;    public JwtFilter(){        logger= LoggerFactory.getLogger("JwtFilter");    }    @Override    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {        String requestUrl=exchange.getRequest().getPath().toString();        ServerHttpResponse response = exchange.getResponse();        /*过滤掉获取token的接口*/        if(requestUrl.toLowerCase().equals("/eureka-identity/api/token/gettoken")){            return chain.filter(exchange);        }        //获取token        String token=exchange.getRequest().getHeaders().getFirst("Authorization");        //没有token返回未认证        if(token==null||token==""){            response.setStatusCode(HttpStatus.UNAUTHORIZED);            return response.setComplete();        }        try{            this.getJwtByToken(token,jwtKey,null);            return chain.filter(exchange);        }        catch(Exception ex){            logger.error(ex.getMessage());            response.setStatusCode(HttpStatus.UNAUTHORIZED);            return response.setComplete();        }    }     @Override    public int getOrder() {        return 0;    }    private DecodedJWT getJwtByToken(String token, String key, Map claims) throws Exception{        Algorithm algorithm = Algorithm.HMAC256(key);        Verification verifier= JWT.require(algorithm)                .withIssuer("liujb");        if(claims!=null){            claims.forEach((mapKey,mapValue)->{                verifier.withClaim(mapKey,mapValue);            });}        JWTVerifier ver= verifier.build();        DecodedJWT jwt=ver.verify(token);        return jwt;    }}

这里只做了简单的认证,以此基础进行深化,如根据不同的服务名称要求不同的claim。 

3,测试

加入Authorization关,值为之前获取的jwt token

39fa79d34e9e4498a041bf8083a081d3

如果token不对或没有token都将返回401状态值

1188a2b3d7914fd4a60fa5232bf71f32
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值