基于JWT(Json Web Token)的授权方式

JWT 是JSON风格轻量级的授权和身份认证规范,可实现无状态、分布式的Web应用授权;

从客户端请求服务器获取token, 用该token 去访问实现了jwt认证的web服务器。 token 可保存自定义信息,如用户基本信息, web服务器用key去解析token,就获取到请求用户的信息了;
很方便解决跨域授权的问题,因为跨域无法共享cookie,.net平台集成的 FormAuthentication 认证系统是基于Session保存授权信息,拿不到cookie就无法认证,用jwt完美解决了。
很多时候,web服务器和授权服务器是同一个项目,所以也可以用以下架构:

实现JWT授权

1.vs2015 新建一个WebApi,安装下面的库,可用nuget 或 命令安装:

install-package Thinktecture.IdentityModel.Core
install-package Microsoft.Owin.Security.Jwt

2.把Startup.Auth.cs 下的 ConfigureAuth 方法清空掉,改为:

public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
var issuer = ConfigurationManager.AppSettings["issuer"];
var secret = TextEncodings.Base64Url.Decode(Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(ConfigurationManager.AppSettings["secret"]))); //用jwt进行身份认证
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { "Any" },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
}
}); app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
//生产环境设为false
AllowInsecureHttp = true,
//请求token的路径
TokenEndpointPath = new PathString("/oauth2/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(30),
//请求获取token时,验证username, password
Provider = new CustomOAuthProvider(),
//定义token信息格式
AccessTokenFormat = new CustomJwtFormat(issuer, secret),
}); }
}

3.ConfigureAuth中的 AccessTokenFormat = new CustomJwtFormat(issuer, secret)是自定义token 保存的信息格式, CustomJwtFormat.cs 类代码

/// /// 自定义 jwt token 的格式
/// public class CustomJwtFormat : ISecureDataFormat<AuthenticationTicket>
{
private readonly byte[] _secret;
private readonly string _issuer; public CustomJwtFormat(string issuer, byte[] secret)
{
_issuer = issuer;
_secret = secret;
} public string Protect(AuthenticationTicket data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
} var signingKey = new HmacSigningCredentials(_secret);
var issued = data.Properties.IssuedUtc;
var expires = data.Properties.ExpiresUtc; return new JwtSecurityTokenHandler().WriteToken(new JwtSecurityToken(_issuer, "Any", data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey));
} public AuthenticationTicket Unprotect(string protectedText)
{
throw new NotImplementedException();
}
}

4.ConfigureAuth中的 Provider = new CustomOAuthProvider() 是自定义验证username, password 的,可以用它来实现访问数据库的验证业务逻辑,CustomOAuthProvider.cs类代码

/// /// 自定义 jwt oauth 的授权验证
/// public class CustomOAuthProvider : OAuthAuthorizationServerProvider
{
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var username = context.UserName;
var password = context.Password;
string userid;
if (!CheckCredential(username, password, out userid))
{
context.SetError("invalid_grant", "The user name or password is incorrect");
context.Rejected();
return Task.FromResult<object>(null);
}
var ticket = new AuthenticationTicket(SetClaimsIdentity(context, userid, username), new AuthenticationProperties());
context.Validated(ticket); return Task.FromResult<object>(null);
} public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return Task.FromResult<object>(null);
} private static ClaimsIdentity SetClaimsIdentity(OAuthGrantResourceOwnerCredentialsContext context, string userid, string usercode)
{
var identity = new ClaimsIdentity("JWT");
identity.AddClaim(new Claim("userid", userid));
identity.AddClaim(new Claim("username", usercode));
return identity;
} private static bool CheckCredential(string usernme, string password, out string userid)
{
var success = false;
// 用户名和密码验证
if (usernme == "admin" && password == "admin")
{
userid = "1";
success = true;
}
else
{
userid = "";
}
return success;
}
}

5.Web.config 添加 issue 和 secret

<appSettings>
<addkey="issuer"value="test"/>
<addkey="secret"value="12345678123456781234567812345678"/>
appSettings>

使用

强烈建议用 chrome 的 postman 插件来调试

  1. 获取token

  2. 用token请求数据

header 要添加 Authorization , 值为: Bearer [token], 获取到的 token 替换 [token], 如

Authorization   Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyaWQiOiIxIiwidXNlcmNvZGUiOiIxIiwiaXNzIjoidGVzdCIsImF1ZCI6IkFueSIsImV4cCI6MTQ4NzI0MTQ5MCwibmJmIjoxNDg0NjQ5NDkwfQ.RaWlJC3OF0RNz4mLtuW4uQtRKDHF8RXwZwzIcbZoNOo

JWT缺点

  1. 一旦拿到token, 可用它访问服务器,直到过期,中间服务器无法控制它,如是它失效(有解决方案: 在 token 中保存信息,可添加额外的验证,如加一个 flag, 把数据库对应的flag失效,来控制token有效性)。
  2. token 的过期时间设置很关键,一般把它设到凌晨少人访问时失效,以免用户使用过程中失效而丢失数据。
  3. token保存的信息有限,且都是字符串。

jwt 无状态分布式授权的更多相关文章

  1. 开箱即用 - jwt 无状态分布式授权

    基于JWT(Json Web Token)的授权方式 JWT 是JSON风格轻量级的授权和身份认证规范,可实现无状态.分布式的Web应用授权: 从客户端请求服务器获取token, 用该token 去访 ...

  2. 基于JWT的无状态分布式授权【本文摘自智车芯官网】

    简介 JWT是一种用于HTTP交互双方之间传递安全信息的简洁的.安全的表述性声明规范.JWT作为一个开发的标准,它定义了一种简洁的,自包含的方法用于通信双发之间以JSON形式安全传递.且因为数字证书的 ...

  3. shiro jwt 构建无状态分布式鉴权体系

    一:JWT 1.令牌构造 JWT(json web token)是可在网络上传输的用于声明某种主张的令牌(token),以JSON 对象为载体的轻量级开放标准(RFC 7519). 一个JWT令牌的定 ...

  4. 基于Volley,Gson封装支持JWT无状态安全验证和数据防篡改的GsonRequest网络请求类

    这段时间做新的Android项目的client和和REST API通讯框架架构设计.使用了非常多新技术,终于的方案也相当简洁优雅.client仅仅须要传Java对象,server端返回json字符串, ...

  5. C#实现JWT无状态验证的实战应用

    前言 本文主要介绍JWT的实战运用. 准备工作 首先我们创建一个Asp.Net的,包含MVC和WebApi的Web项目. 然后使用Nuget搜索JWT,安装JWT类库,如下图. 设计思路 这里我们简单 ...

  6. ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统

    为什么使用 Jwt 最近,移动开发的劲头越来越足,学校搞的各种比赛都需要用手机 APP 来撑场面,所以,作为写后端的,很有必要改进一下以往的基于 Session 的身份认证方式了,理由如下: 移动端经 ...

  7. Spring Boot Security 整合 JWT 实现 无状态的分布式API接口

    简介 JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案.JSON Web Token 入门教程 - 阮一峰,这篇文章可以帮你了解JWT的概念.本文重点讲解Spring Boo ...

  8. JWT+Interceptor实现无状态登录和鉴权

    无状态登录原理 先提一下啥是有状态登录 单台tomcat的情况下:编码的流程如下 前端提交表单里用户的输入的账号密码 后台接受,查数据库, 在数据库中找到用户的信息后,把用户的信息存放到session ...

  9. 从有状态应用(Session)到无状态应用(JWT),以及 SSO 和 OAuth2

    不管用哪种方式认证用户,都可能被中间人攻击窃取 SessionID 或 Token,从而发生 CSRF 攻击.解决方式就是全站 HTTPS.现在 Let's Encrypt 已经支持免费的通配符 HT ...

随机推荐

  1. 前端 img标签显示 base64格式的 图片

    本文链接:https://blog.csdn.net/kukudehui/article/details/80409522在做项目的时候,我从后端返回了一个base64格式的图片文件,想把它渲染在前端 ...

  2. Alibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas

    Arthas 用户文档 — Arthas 3.1.0 文档https://alibaba.github.io/arthas/ alibaba/arthas: Alibaba Java Diagnost ...

  3. SpringCloud-Eureka配置instanceId显示IP

    eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ instance: preferIpAddress: tr ...

  4. [转]EL表达式判断是否为空,判断是否为空字符串

    原文地址:https://blog.csdn.net/zhaofuqiangmycomm/article/details/79442730 El表达式判断是否为空字符串 ${empty 值}  返回t ...

  5. YII2 输出 执行的 SQL 语句,直接用程序输出

    $query = User::find() ->,,,]) ->select(['username']) // 输出SQL语句 $commandQuery = clone $query; ...

  6. typescript命名空间

    /* 命名空间: 在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数.类.接口等放置到命名空间内 同Java的包..Net的命名空间一样,TypeScript的命名空间可以将代码包裹 ...

  7. 编写第一个dart程序hello dart

    /* 入口方法的两种定义方式 main(){ print('hello dart'); } */ ///这也是一个注释 //表示main方法没有返回值 void main(){ print('hell ...

  8. Python3基础 交换两个变量的值

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  9. Android平台云端打包证书使用说明

    原贴:https://ask.dcloud.net.cn/article/35985 Android平台云端打包证书使用说明 分类:HBuilderX 证书 Android 签名证书是一个应用的所有者 ...

  10. mobile crane 1

    void MobileCrane::rotateRope2() { //double r_angle1 = rotateRope + rorate3; //std::cout << &qu ...