jwt认证授权方案优化

jwt是保存在客户端的字符串,里面携带了用户的一些基本信息,每次请求时候由客户端携带jwt token去后端请求接口。

jwt认证授权过程

一般jwt认证授权过程可以描述如下:

  1. 用户登录通过系统的认证后,系统颁发jwt令牌给该用户,用户将该jwt存储起来,可存放在cookie,header,或者localstorage等;
  2. 用户发送请求,请求携带上系统颁发的jwt去请求服务;
  3. 服务端解析该jwt令牌,若是解析且验证通过,将解析后的用户信息存储在ThreadLocal容器,作为该请求的一个识别体;否则将提示授权失败。
  4. 在jwt有效期内,用户便可以通过该令牌进行服务资源的请求。

jwt一旦颁发就会一直有效,直到有效期过后;为了更好的利用http无状态特性,服务端也没有对jwt进行缓存或者进行会话管理,这样在此期间用户退出系统后,jwt的有效期还没有到,其他用户便可以窃取该token进行服务资源的请求;
区别于cookie-session的鉴权方式,在jwt鉴权中,仍然存在一定的身份认证漏洞;这是很危险的一个过程,也是一个缺陷。

对比cookie-session

session-cookie,我们暂且不考虑分布式情况下session共享和其他可能的的安全攻击;
jwt客户端持有,sessionId服务端保存;这种方式让http无状态的请求变成了有状态的。
用户通过cookie携带sessionId,去请求服务资源,后台服务资源根据sessionId来区分用户,请求来源,是否授权等;
这种虽然是有状态的,但是可以由服务端去控制用户的权限;
借鉴:jwt是否也能够用这种方式解决这个jwt管理工作呢?
当然可以,除了在客户端保持jwt,在服务端也可维持一份jwt,
so问题来了,那选取jwt是为了利用jwt的无状态,将jwt保存在服务端,那又跟session-cookie有什么区别呢?
区别当然是有的:

  1. session存储数据相对较多,要在服务端维持所有的sessionId表,用户同时访问会占用更高的处理内存;
    当然你可以设置个外置缓存,如redis来解决内存消耗,顺便还可以解决分布式session共享问题;相比于session来说,我们可以在服务端维持一份jwt黑白名单,通过jwt过期时间能够很好地控制jwt在服务端保持的总量;
    比如某些由于主动退出或者主动作废的jwt,便可以通过redis进行维护,redis将jwt中的jti字段进行存储和exp字段进行过期时间的维护;在结合系统可以设置jwt过期时间短一点,这样就能很好的控制jwt黑白名单的增长。

  2. jwt本身提供了jti字段,这个默认字段含义是JWT ID,这个按照官方说明,就是说这个不建议将jwt字符串整体存储在服务端保持,但可以短时间去缓存这个jwt;
    可以使用jti字段(jti是有效载荷里面的一个预设字段)
    RFC 7591中的定义:

    The “jti” (JWT ID) claim provides a unique identifier for the JWT.
    The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that
    the same value will be accidentally assigned to a different data object;
    if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well.
    The “jti” claim can be used to prevent the JWT from being replayed.
    The “jti” value is a case- sensitive string. Use of this claim is OPTIONAL.

    无状态请求可以简单理解为:前后请求无关联无上下文,服务端处理每个请求的全部信息必须只来自该请求,以及其他服务端保持的可以被所有请求共用的公共信息(外部存储介质),如redis里面的公共信息。
    因此这并不违反无状态。

jwt解决方案优化

添加黑名单机制:

  1. 每次生成颁发jwt时候,附加生成一个jti字段来标识每个jwt;
  2. 使用redis来缓存jwt,存储结构选取string类型,设置key格式(suggestion):jwt:user_id:jti 例如:jwt:17788822333:dakhawadjfaihf
  3. 为了防止redis挂掉中断,可以加入一个数据表进行临时替代品,id可取jti字段值。
  4. 用户主动退出时候,我们在登出逻辑中将该jwt放入黑名单中,设置失效时间即为jwt过期时间。(jwt一旦颁发变不可更改,这样设置时间是经过考量的,具体略;
  5. 每次请求校验时候,除了校验jwt本身,还要去黑名单中去查询一下,如果有,即使解析通过也不得授权;

补充

后续将对jwt payload预设内容做出如下优化

预设字段说明描述
iss签发者存放签发系统或其子系统的标识,用来后续区分颁发者信息做不同处理
sub所面向的用户存放用户的唯一标识信息,如UserID/UserName/UserPhone等
aud接收的受众存放设备标识,如ip,登录设备是IOS还是Android等
jtijwt id存放jwt令牌的唯一标识,可作为数据库主键id,redis缓存key
exp过期时间标识令牌失效时间,Unix时间戳(s)
iat签发时间标识令牌颁发时间,Unix时间戳(s)
nbf之前时间不可用标识令牌生效时间,Unix时间戳(s)

all done

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Blazor是一种基于WebAssembly的新型Web开发框架,可以使用C#语言开发客户端应用程序。它提供了一种方便的方式来实现JWT认证授权。 在Blazor应用程序中,您可以使用ASP.NET Core Identity和JSON Web Token(JWT)来实现JWT认证授权。首先,您需要在ASP.NET Core应用程序中配置JWT认证服务。然后,您可以使用Identity提供的API来管理用户和角色,以及实现基于角色的授权策略。 接下来,您需要在Blazor组件中使用`[Authorize]`属性来标记需要授权才能访问的组件。这将要求用户登录,并检查他们是否具有访问该组件的权限。 最后,您可以使用JWT来验证用户身份,并根据用户的角色和权限来授权访问。 下面是一个示例,演示如何在Blazor应用程序中使用JWT认证授权: ``` @page "/myprotectedpage" @attribute [Authorize(Roles = "Admin")] <h1>Welcome to the protected page!</h1> @code { [Inject] private IAccessTokenProvider TokenProvider { get; set; } private async Task<string> GetAccessTokenAsync() { var tokenResult = await TokenProvider.RequestAccessToken(); if (tokenResult.TryGetToken(out var token)) { return token.Value; } else { return null; } } protected override async Task OnInitializedAsync() { var accessToken = await GetAccessTokenAsync(); if (accessToken != null) { // Verify the token and extract the user's claims var handler = new JwtSecurityTokenHandler(); var token = handler.ReadJwtToken(accessToken); var userId = token.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; var roles = token.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value).ToList(); // Check if the user has the required role if (!roles.Contains("Admin")) { NavigationManager.NavigateTo("/accessdenied"); } } else { NavigationManager.NavigateTo("/login"); } } } ``` 在上面的示例中,我们使用`[Authorize(Roles = "Admin")]`属性来标记需要“Admin”角色才能访问的组件。然后,我们使用`IAccessTokenProvider`来获取JWT访问令牌,并验证令牌以确定用户的身份和角色。如果用户没有所需的角色,我们将重定向到一个名为“accessdenied”的页面。 希望这个示例能够帮助您实现Blazor中的JWT认证授权
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值