手机版

ASP.NET基于JWT的web api认证和跨域调用实践

时间:2021-08-31 来源:互联网 编辑:宝哥软件园 浏览:

随着多终端的出现,越来越多的网站以RESTful Web API的形式对外提供服务,很多网站也采用前端分离的模式进行开发。因此,身份验证方法可能不同于传统的基于cookie的会话标识方法。除了跨域提交cookie这个烦人的问题,更重要的是,有些终端可能根本不支持cookie。

Json Web token(jwt)是一种很好的认证和授权方案。简单来说,在调用api时,调用者附加一个由api发出的令牌来验证调用者的授权信息。

然而,由于时间限制,jwt将不再描述。详情请参考jwt.io

下面是一个基于jwt认证的ASP.NET web API的演示。为了模拟前端分离的开发模式,该演示包括一个静态页面站点(IIS中的路径为http://localhost:8057)和一个web API站点(http://localhost:8056)。静态页面站点中只有一个index.html,它包括两个功能:一个登录功能和调用需要身份验证才能获取数据的接口。所有接口都是通过ajax调用的。

下面是要写的主要代码,让我们一步一步地写代码。

开发登录界面

因为我们使用jwt技术,所以我们首先添加一个框架来封装jwt在nuget上的使用。我使用了以下框架。

根据jwt的定义,jwt中携带用户身份信息的数据段称为有效载荷。需要创建一个类“AuthInfo”来表示有效负载。

///summary////表示jwt////summary公共类auth info {///summary///username////summary公共字符串username { get设置;}///summary////角色列表,可以用来记录用户的角色,相当于声明的概念(如果不知道声明是什么,请谷歌一下‘基于声明的权限控制’)//////summary public liststring roles { get;设置;}///summary////是管理员////summary public bool是admin { get设置;}然后写登录界面

公共类LoginController : API controller { public LoginResult Post([from body]LoginRequest request request){ LoginResult RS=new LoginResult();//假设用户名为‘admin’,密码为‘123’if(request。username==' admin '请求。password==' 123 '){//如果用户登录成功,就可以获取用户的身份数据。在实际开发中,当然需要获取用户在数据库中的角色和权限auth info auth info=new auth info { is admin=true,roles=new liststring {'admin ',' owner'},username=' admin ' };尝试{//生成令牌,securekey是配置的web.config中用于加密令牌的密钥,你不能告诉别人byte[]key=encoding . default . getbytes(configuration manager . app settings[' securekey '])即使你被杀了;//使用HS256加密算法stringtoken=jwt . jsonwebtoken . encode(authinfo,key,jwt . jwthashalgorithm . HS256);rs。Token=tokenrs。成功=真;}捕捉{ rs。成功=假;卢比消息=“登录失败”;} } else { rs。成功=假;卢比消息=“用户名或密码不正确”;}返回RS;}}这里,我们已经编写了登录界面。如果用户名和密码正确,登录界面将生成一个包含用户身份信息的令牌作为响应。接收到令牌后,前端需要将令牌附加到后续请求中,以证明其身份。

如认证

接下来,我们需要编写与权限控制和令牌解析相关的代码。

web api框架提供authorizeittribute,用于在调用api之前验证请求。可以通过重写authorizeittribute来自定义验证逻辑。授权方法

公共类apiauthorizeattribute : AuthorizeAttribute { protected override bool isaauthorized(Httpactioncontext action context){//前端请求API并将令牌存储在名为' auth '的请求头中;var auth header=来自操作上下文中的h . request . headers,其中h.key==' auth '选择h . value . first ordefault();if (authHeader!=null) {字符串标记=authHeader。first ordefault();if(!字符串。isnullrempty(令牌)){ try {//解密令牌。String securekey=system。configuration . configuration manager . app settings[' securekey '];授权信息授权信息=JWT。JsonWebToken . decodobjectauthinfo(token,secureKey);if (authInfo!=null) {//存储后续调用action context . request context . route data . values . add(' auth ',authinfo)的用户信息;返回真;}否则返回false} catch { return false} } else返回false}否则返回false} }

假设接口返回与用户相关的敏感信息,编写一个受AuthorizeAttribute保护的接口。

需要注意的是,由于前端站点和web api站点使用不同的端口,即使方案(http)和地址相同,仍然会造成跨域访问。因此,必须为web api站点启用允许跨域访问。实际上,CORS(跨域资源共享)或者所谓的同源策略是浏览器上的一个概念,服务器需要做的就是根据需要返回几个响应头:

访问控制允许源:表示允许这些源(域)访问该站点。访问控制允许头:表示站点允许那些定制的请求头(我们通过jquery.ajax发送一个名为‘auth’的包含token的请求头,因此需要设置api站点允许‘auth’请求头。)访问控制允许方法:表示站点允许那些请求谓词(GET、POST、OPTIONS、PUT.).在ASP.NET网络应用编程接口中,有两种方法可以实现跨域访问:

首先是安装‘微软’。在Nuget上安装. AspNet.WebApi.Cors包,并在Api控制器上使用[EnableCors]功能

二是在web.config中配置:

您必须注释掉' remove name=' options verbhandler '/'以启用选项谓词处理,否则在跨域访问时prefight将失败。

返回用户相关敏感信息的api代码如下:

//标记控制器需要身份验证[API authorize]公共类用户控制器: API控制器{public string get () {//获取回用户信息(通过解析API authorize中token的有效载荷并保存在RouteData中)authinfo authinfo=this。request context . route data . values[' auth ']作为authinfoIf (authInfo==null)返回“无效的接受信息”;否则返回字符串。格式(' Hello :{0},数据获取成功',authInfo。用户名);}}前端站点

至此,api站点的代码已经编写完成。然后写前端站点的代码。

前端站点只有一个html页面,包含两个简单的功能:调用登录界面登录,调用认证保护的界面获取数据

首页的关键脚本代码如下:

$(function () {//调用api站点的登录接口,成功登录后接口返回一个token。$('#login ')。on('click ',function () { $。Ajax({ URL : ' http://localhost :8056/API/log in ',data: $('form ')。serialize(),method: 'post ',Success3360函数(数据){if(数据。成功){//为简单起见,将token保存在全局变量中。window.token=数据。代币;警报(“登录成功”);} else {alert('登录失败: '数据。消息);} } });});//调用api站点的接口获取数据,需要认证。$('#invoke ')。on('click ',function () { $。Ajax({ URL : ' http://localhost :8056/API/user ',method: 'get ',Headers : { ' auth ' : window . token },//通过请求头发送token,并放弃发送cookie,完成:函数(jqxhr,text status){ alert(jqxhr . responsetext);}, });});});/script接下来,在不登录或不登录的情况下,调用接口获取数据,使用fiddler监控请求和响应的过程。

不登录直接按“通话界面”,服务器返回401未授权信息

以下是通信情况:

这一次,先登录,然后调用接口,同时也监控fiddler中的通信。

在fiddler中,可以看到整个流程浏览器发送了三个请求,分别是登录、调用接口前的prefight和实际调用接口:

让我们来看看每一次交流

登录过程:

预发光

实际上发送一个get请求来调用接口并获取数据

至此,基于JWT的认证和跨域访问演示已经完成。请改正任何错误

以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。

版权声明:ASP.NET基于JWT的web api认证和跨域调用实践是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。