开箱即用 - 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{    
                      //生产环境设为falseAllowInsecureHttp = true,              
                        //请求token的路径TokenEndpointPath = new PathString("/oauth2/token"),AccessTokenExpireTimeSpan = TimeSpan.FromDays(30),                //请求获取token时,验证username, passwordProvider = 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.eyJ1c2VyaWQiOiIxIiwidXNlcmNvZG
UiOiIxIiwiaXNzIjoidGVzdCIsImF1ZCI6IkFueSIsImV4cCI6MTQ4NzI0MTQ5MCwibmJmIjo
xNDg0NjQ5NDkwfQ
.RaWlJC3OF0RNz4mLtuW4uQtRKDHF8RXwZwzIcbZoNOo

JWT缺点

  1. 一旦拿到token, 可用它访问服务器,直到过期,中间服务器无法控制它,如是它失效(有解决方案: 在 token 中保存信息,可添加额外的验证,如加一个 flag, 把数据库对应的flag失效,来控制token有效性)。

  2. token 的过期时间设置很关键,一般把它设到凌晨少人访问时失效,以免用户使用过程中失效而丢失数据。

  3. token保存的信息有限,且都是字符串。

相关文章: 

原文地址:http://www.cnblogs.com/grissom007/p/6294746.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

List VS Set

Duang Duang Duang面试官来啦&#xff0c;快坐好&#xff0c;摆好姿势。 好了&#xff0c;我要开始提问了&#xff1a; 问&#xff1a;Set集合与List集合有什么区别呢&#xff1f; 答&#xff1a;Set集合中的数据不可重复&#xff0c;数据是无序的&#xff0c;List集合的数据可…

外部访问docker容器(docker run -p/-P 指令) docker run -d -p 5000:5000 {hostPort:containerPort(映射所有接口地}

https://www.cnblogs.com/williamjie/p/9915019.html &#xff08;2&#xff09;-p&#xff08;小写&#xff09;则可以指定要映射的IP和端口&#xff0c;但是在一个指定端口上只可以绑定一个容器。支持的格式有 hostPort:containerPort、ip:hostPort:containerPort、 ip::cont…

读取/书写Java的XML格式properties文件

转载自 读取/书写Java的XML格式properties文件 在JDK5中&#xff0c;properties文件的格式可以由XML构成&#xff0c;这里给出了一个读取/书写XML格式properties文件的例子。因为使用了XML&#xff0c;所以文件内容支持了CJKV(中文、日文、韩文、越南语)。可以直接书写、调用…

使用泛型前 VS 使用泛型后

不使用泛型&#xff1a; List list1 new ArrayList(); list1.add("www.educoder.net"); String str1 (String)list1.get(0);使用泛型&#xff1a; List<String> list2 new ArrayList<String>(); list2.add("www.educoder.net"); String s…

ssh报错java.lang.ClassCastException: com.sun.proxy.$Proxy6 cannot be cast to org.service.impl.EmpServi

错误如下&#xff1a; java.lang.ClassCastException: com.sun.proxy.$Proxy6 cannot be cast to org.service.impl.EmpServiceImpl at org.service.impl.EmpServiceImplTest.init(EmpServiceImplTest.java:44)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Metho…

去掉字符串后面所有的0 去掉字符串前面或后面的0;

https://blog.csdn.net/weixin_43844810/article/details/94577879 去掉字符串前面或后面的0&#xff1b; 养猫还是养狗&#xff1f; 2019-07-03 17:10:23 4492 收藏 1 分类专栏&#xff1a; 工作 版权 方法一&#xff1a; int a 0; //将油站编码前的0去掉 …

Java类加载器总结

转载自 Java类加载器总结 1.类的加载过程 JVM将类加载过程分为三个步骤&#xff1a;装载&#xff08;Load&#xff09;&#xff0c;链接&#xff08;Link&#xff09;和初始化(Initialize)链接又分为三个步骤&#xff0c;如下图所示&#xff1a; 1) 装载&#xff1a;查找并…

ssh根据姓名查询的时候报错java.lang.IndexOutOfBoundsException: Remember that ordinal parameters are 1-based!

错误如下&#xff1a; java.lang.IndexOutOfBoundsException: Remember that ordinal parameters are 1-based! at org.hibernate.engine.query.ParameterMetadata.getOrdinalParameterDescriptor(ParameterMetadata.java:79)at org.hibernate.engine.query.ParameterMetadat…

拆分字符串

String.split()拆分字符串 lang包String类的split()方法 public String[] split(String regex) public String[] split(String regex&#xff0c;int limit) //limit 参数控制模式应用的次数&#xff0c;因此影响所得数组的长度 拆分示例:public class SplitDemo {public sta…

MyBatis-Plus EntityWrapper的使用 wrapper le ge

https://blog.csdn.net/shujuelin/article/details/99568651 MyBatis-Plus EntityWrapper的使用 脚丫先生 2019-08-14 14:43:43 2660 收藏 分类专栏&#xff1a; javaee 版权 调度Airflow 本专刊主要以调度系统Airflow详细讲解(会把工作中对于调度系统的docker容器化部署、…

又踩.NET Core的坑:在同步方法中调用异步方法Wait时发生死锁(deadlock)

之前在将 Memcached 客户端 EnyimMemcached 迁移 .NET Core 时被这个“坑”坑的刻骨铭心&#xff08;详见以下链接&#xff09;&#xff0c;当时以为只是在构造函数中调用异步方法&#xff08;注&#xff1a;这里的异步方法都是指基于Task的&#xff09;才会出线死锁&#xff0…

jvm类加载器以及双亲委派

转载自 jvm类加载器以及双亲委派 首先来了解几个概念&#xff1a; 类加载&#xff1a; 概念&#xff1a;虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验--转换解析--初始化&#xff0c;最终形成能被java虚拟机直接使用的java类型&#xff0c;就是jvm…

java实现人脸识别源码【含测试效果图】——实体类(Users)

/** * Title: Users.java * Package org.entity * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-9-22 下午7:01:09 * version V1.0 */ package org.entity;/** * * 项目名称&#xff1a;test_face_photo * 类名…

对字符进行转义

“|”、“.”、“*”、“”、“\”等不是有效的模式匹配规则表达式&#xff0c;是转义字符&#xff0c;使用split()方法时必须得加"\"才行。

分布式系统搭建:服务发现揭秘

CAP理论 加州大学终身教授与著名计算机科学家Eric Allen Brewer在90年代末提出了CAP理论&#xff0c;理论断言任一个基于网络的分布式系统&#xff0c;最多只能满足“数据一致性”、“可用性”、“分区容错性”三要素中的两个要素。 该理论后被MIT证明可行&#xff0c;故架构师…

SSL / TLS 协议运行机制详解

转载自 SSL / TLS 协议运行机制详解 互联网的通信安全&#xff0c;建立在SSL/TLS协议之上。 本文简要介绍SSL/TLS协议的运行机制。文章的重点是设计思想和运行过程&#xff0c;不涉及具体的实现细节。如果想了解这方面的内容&#xff0c;请参阅RFC文档。 一、作用 不使用SS…

java实现人脸识别源码【含测试效果图】——Dao层(BaseDao)

package org.dao;import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List;/*** * * 项目名称&#xff1a;test_face_photo * 类名称&#…

统计单词出现的次数并进行排

统计 统计相同单词的次数 //使用map集合进行存储 String s"Day by Day"; Map<String,Integer> mapnew HashMap<String,Integer>(); StringTokenizer tokenizernew StringTokenizer(s); int count;//记录次数 String word;//单个单词 while(tokenizer.ha…

Mybatisplus 自动生成字段 强制覆盖 null或者空字符串也覆盖

ApiModelProperty(value "证件号码&#xff0c;现在是身份证号") TableField("id_number") private String idNumber;ApiModelProperty(value "证件到期日期") TableField(value "id_card_expire_date",fill FieldFill.UPDATE) priv…

在ASP.NET Core Web API上使用Swagger提供API文档

我在开发自己的博客系统&#xff08;http://daxnet.me&#xff09;时&#xff0c;给自己的RESTful服务增加了基于Swagger的API文档功能。当设置IISExpress的默认启动路由到Swagger的API文档页面后&#xff0c;在IISExpress启动Web API站点后&#xff0c;会自动重定向到API文档页…