基于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 类代码


/// <summary>
/// 自定义 jwt token 的格式
/// </summary>
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类代码

    /// <summary>
/// 自定义 jwt oauth 的授权验证
/// </summary>
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>
<add key="issuer" value="test"/>
<!--32个字符的secret-->
<add key="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保存的信息有限,且都是字符串。

Demo源码

开箱即用 - 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. 编译内核启用iptables及netfilter

    在Network Packet Filtering Framework(Netfilter)一节中还有两个额外的配置节——Core Netfilter Configuration(核心Netfilte ...

  2. ural1414 Astronomical Database

    Astronomical Database Time limit: 2.0 secondMemory limit: 64 MB After the Hubble telescope had been ...

  3. Bessie Goes Moo

    Bessie Goes Moo 题目描述 Farmer John and Bessie the cow love to exchange math puzzles in their free time ...

  4. Bootstrap Table的使用

    前言:BootstrapTable基于Bootstrap,Bootstrap基于jquery,所以需要引入jquery后再引入bootstrap. <link href="${ctx} ...

  5. Sping--Id, Name

    bean, id/name 都可以 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=& ...

  6. Linux下部署

    moto66@163.com       0144586wei 郭 2015/3/23 星期一 9:29:38 服务器密码:0144586Wei120.26.62.247

  7. java学习(二)--excel导出

    public static String writeFile(String fileName, String[][] content) { WritableWorkbook wwb = null; S ...

  8. C语言-知识点及学习路线

    最近进行了为期两周的C语言培训,把几年前学过的C语言又重新学习了一遍,然后根据学习的内容和过程,总结了一下学习路线.这是基本的C语言学习路线,相当于编程语言类的基础,再根据自己究竟是要做单片机开发,还 ...

  9. Zju1290 Word-Search Wonder(http://begin.lydsy.com/JudgeOnline/problem.php?id=2768)

    2768: Zju1290 Word-Search Wonder Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 4  Solved: 2[Submit] ...

  10. JAVA WEB 中的编码分析

    JAVA WEB 中的编码分析 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src {background-co ...