jwt 无状态分布式授权
基于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 插件来调试
获取token
用token请求数据
header 要添加 Authorization , 值为: Bearer [token], 获取到的 token 替换 [token], 如
Authorization Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyaWQiOiIxIiwidXNlcmNvZGUiOiIxIiwiaXNzIjoidGVzdCIsImF1ZCI6IkFueSIsImV4cCI6MTQ4NzI0MTQ5MCwibmJmIjoxNDg0NjQ5NDkwfQ.RaWlJC3OF0RNz4mLtuW4uQtRKDHF8RXwZwzIcbZoNOo
JWT缺点
- 一旦拿到token, 可用它访问服务器,直到过期,中间服务器无法控制它,如是它失效(有解决方案: 在 token 中保存信息,可添加额外的验证,如加一个 flag, 把数据库对应的flag失效,来控制token有效性)。
- token 的过期时间设置很关键,一般把它设到凌晨少人访问时失效,以免用户使用过程中失效而丢失数据。
- token保存的信息有限,且都是字符串。
jwt 无状态分布式授权的更多相关文章
- 开箱即用 - jwt 无状态分布式授权
基于JWT(Json Web Token)的授权方式 JWT 是JSON风格轻量级的授权和身份认证规范,可实现无状态.分布式的Web应用授权: 从客户端请求服务器获取token, 用该token 去访 ...
- 基于JWT的无状态分布式授权【本文摘自智车芯官网】
简介 JWT是一种用于HTTP交互双方之间传递安全信息的简洁的.安全的表述性声明规范.JWT作为一个开发的标准,它定义了一种简洁的,自包含的方法用于通信双发之间以JSON形式安全传递.且因为数字证书的 ...
- shiro jwt 构建无状态分布式鉴权体系
一:JWT 1.令牌构造 JWT(json web token)是可在网络上传输的用于声明某种主张的令牌(token),以JSON 对象为载体的轻量级开放标准(RFC 7519). 一个JWT令牌的定 ...
- 基于Volley,Gson封装支持JWT无状态安全验证和数据防篡改的GsonRequest网络请求类
这段时间做新的Android项目的client和和REST API通讯框架架构设计.使用了非常多新技术,终于的方案也相当简洁优雅.client仅仅须要传Java对象,server端返回json字符串, ...
- C#实现JWT无状态验证的实战应用
前言 本文主要介绍JWT的实战运用. 准备工作 首先我们创建一个Asp.Net的,包含MVC和WebApi的Web项目. 然后使用Nuget搜索JWT,安装JWT类库,如下图. 设计思路 这里我们简单 ...
- ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统
为什么使用 Jwt 最近,移动开发的劲头越来越足,学校搞的各种比赛都需要用手机 APP 来撑场面,所以,作为写后端的,很有必要改进一下以往的基于 Session 的身份认证方式了,理由如下: 移动端经 ...
- Spring Boot Security 整合 JWT 实现 无状态的分布式API接口
简介 JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案.JSON Web Token 入门教程 - 阮一峰,这篇文章可以帮你了解JWT的概念.本文重点讲解Spring Boo ...
- JWT+Interceptor实现无状态登录和鉴权
无状态登录原理 先提一下啥是有状态登录 单台tomcat的情况下:编码的流程如下 前端提交表单里用户的输入的账号密码 后台接受,查数据库, 在数据库中找到用户的信息后,把用户的信息存放到session ...
- 从有状态应用(Session)到无状态应用(JWT),以及 SSO 和 OAuth2
不管用哪种方式认证用户,都可能被中间人攻击窃取 SessionID 或 Token,从而发生 CSRF 攻击.解决方式就是全站 HTTPS.现在 Let's Encrypt 已经支持免费的通配符 HT ...
随机推荐
- 前端 img标签显示 base64格式的 图片
本文链接:https://blog.csdn.net/kukudehui/article/details/80409522在做项目的时候,我从后端返回了一个base64格式的图片文件,想把它渲染在前端 ...
- Alibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas
Arthas 用户文档 — Arthas 3.1.0 文档https://alibaba.github.io/arthas/ alibaba/arthas: Alibaba Java Diagnost ...
- SpringCloud-Eureka配置instanceId显示IP
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ instance: preferIpAddress: tr ...
- [转]EL表达式判断是否为空,判断是否为空字符串
原文地址:https://blog.csdn.net/zhaofuqiangmycomm/article/details/79442730 El表达式判断是否为空字符串 ${empty 值} 返回t ...
- YII2 输出 执行的 SQL 语句,直接用程序输出
$query = User::find() ->,,,]) ->select(['username']) // 输出SQL语句 $commandQuery = clone $query; ...
- typescript命名空间
/* 命名空间: 在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数.类.接口等放置到命名空间内 同Java的包..Net的命名空间一样,TypeScript的命名空间可以将代码包裹 ...
- 编写第一个dart程序hello dart
/* 入口方法的两种定义方式 main(){ print('hello dart'); } */ ///这也是一个注释 //表示main方法没有返回值 void main(){ print('hell ...
- Python3基础 交换两个变量的值
Python : 3.7.3 OS : Ubuntu 18.04.2 LTS IDE : pycharm-community-2019.1.3 ...
- Android平台云端打包证书使用说明
原贴:https://ask.dcloud.net.cn/article/35985 Android平台云端打包证书使用说明 分类:HBuilderX 证书 Android 签名证书是一个应用的所有者 ...
- mobile crane 1
void MobileCrane::rotateRope2() { //double r_angle1 = rotateRope + rorate3; //std::cout << &qu ...