博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Web API 2基于令牌的身份验证
阅读量:5064 次
发布时间:2019-06-12

本文共 7645 字,大约阅读时间需要 25 分钟。

基于令牌的认证

    我们知道WEB网站的身份验证一般通过session或者cookie完成的,登录成功后客户端发送的任何请求都带上cookie,服务端根据客户端发送来的cookie来识别用户。

    WEB API使用这样的方法不是很适合,于是就有了基于令牌的认证,使用令牌认证有几个好处:可扩展性、松散耦合、移动终端调用比较简单等等,别人都用上了,你还有理由不用吗?

    下面我们花个20分钟的时间来实现一个简单的WEB API token认证:

 

Step 1: 新建一个空的WEB API项目,项目名称就设置为WebApi

 

Step 2: 在Models目录下新建一个 Product 类 :

using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace WebApi.Models{    public class Product    {        public int Id { get; set; }        public string Name { get; set; }        public string Category { get; set; }        public decimal Price { get; set; }    }}

Step 3:在Controllers目录下新建一个 ProductsController 类

using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Web.Http;using WebApi.Models;namespace WebApi.Controllers{    [RoutePrefix("api/Products")]    public class ProductsController : ApiController    {        Product[] products = new Product[]          {              new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },              new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },              new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }          };        public IEnumerable
GetAllProducts() { return products; } public Product GetProductById(int id) { var product = products.FirstOrDefault((p) => p.Id == id); if (product == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } return product; } public IEnumerable
GetProductsByCategory(string category) { return products.Where(p => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase)); } }}

F5运行后就可以使用这个简单的WebApi了,测试api可以使用Postman工具:

    获取所有数据  http://localhost:1234/api/products

    获取内码为1的数据  http://localhost:1234/api/products/1

    查询category=的数据  http://localhost:1234/api/products?category=Groceries

 

    可以看到这个产品的API是公开访问的,没有任何验证,这样不是很安全,下一步我将加上token验证。

 

Step 4:安装所需的NuGet包:

打开NuGet包管理器控制台,然后输入如下指令:

Install-Package Microsoft.AspNet.WebApi.Owin -Version 5.1.2Install-Package Microsoft.Owin.Host.SystemWeb -Version 2.1.0Install-Package Microsoft.AspNet.Identity.Owin -Version 2.0.1 Install-Package Microsoft.Owin.Cors -Version 2.1.0 Install-Package EntityFramework -Version 6.0.0

Step 5:在项目根目录下添加Owin“Startup”类

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Http;using Owin;using Microsoft.Owin;using Microsoft.Owin.Security.OAuth;[assembly: OwinStartup(typeof(WebApi.Startup))]namespace WebApi{    public class Startup    {        public void Configuration(IAppBuilder app)        {            HttpConfiguration config = new HttpConfiguration();            ConfigureOAuth(app);            WebApiConfig.Register(config);            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);            app.UseWebApi(config);        }        public void ConfigureOAuth(IAppBuilder app)        {            OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()            {                AllowInsecureHttp = true,                TokenEndpointPath = new PathString("/token"),                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),                Provider = new SimpleAuthorizationServerProvider()            };            app.UseOAuthAuthorizationServer(OAuthServerOptions);            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());        }    }}

 

Step 6:删除Global.asax 

我们已经设置了Setup类,就不需要Global了,删掉干净;

 

Step 7:在项目根目录下添加验证类 SimpleAuthorizationServerProvider,为了简单用户的验证部分我们省略掉;

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Threading;using System.Threading.Tasks;using Microsoft.Owin;using Microsoft.Owin.Security.OAuth;using System.Security.Claims;namespace WebApi{    public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider    {        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)        {            context.Validated();        }        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)        {            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });            /*             * 对用户名、密码进行数据校验,这里我们省略            using (AuthRepository _repo = new AuthRepository())            {                IdentityUser user = await _repo.FindUser(context.UserName, context.Password);                if (user == null)                {                    context.SetError("invalid_grant", "The user name or password is incorrect.");                    return;                }            }*/            var identity = new ClaimsIdentity(context.Options.AuthenticationType);            identity.AddClaim(new Claim("sub", context.UserName));            identity.AddClaim(new Claim("role", "user"));            context.Validated(identity);        }    }}

 

Step 7:让CORS起作用

在ASP.NET Web API中启用OAuth的Access Token验证非常简单,只需在相应的Controller或Action加上[Authorize]标记

修改ProductsController类

using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Web.Http;using WebApi.Models;namespace WebApi.Controllers{    public class ProductsController : ApiController    {        Product[] products = new Product[]          {              new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },              new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },              new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }          };        [Authorize]        [Route("")]        public IEnumerable
GetAllProducts() { return products; } [Authorize] public Product GetProductById(int id) { var product = products.FirstOrDefault((p) => p.Id == id); if (product == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } return product; } [AllowAnonymous] public IEnumerable
GetProductsByCategory(string category) { return products.Where(p => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase)); } }}

 

现在我们再次直接GET http://localhost:23477/api/products/ 会返回401错误,请求被拒绝

 

获取token, POST   http://localhost:23477/token

参数BODY x-www-form-urlencoded 格式:

grant_type=password

username=admin 

password=123456

返回200状态,内容为:

{  "access_token": "eLjAu3Alm2YWjJKXmX_fLY07P6vbIzxasFECkDap3KIE0Ydp7IGhTgrzWLtPdgrK46rfAB-OmJSG5C8Bh-PkfG3XrGS0uDea2KBXyoWSR11evTGJiVIyXny3Ih2DkH04qH2T_Ar4kIjcAngPtUnsEVex26tV4QHIrjCq5SlkOdfdAa9Pnl98QVwYH47yO-zlc55bwMgpR2J4fQLyNzWVHNZpH3DbOcHQ3Yenemr6XhM",  "token_type": "bearer",  "expires_in": 86399}

只要在http请求头中加上Authorization:bearer Token就可以成功访问API就成功了:

GET   http://localhost:23477/api/products/

Authorization : bearer eLjAu3Alm2YWjJKXmX_fLY07P6vbIzxasFECkDap3KIE0Ydp7IGhTgrzWLtPdgrK46rfAB-OmJSG5C8Bh-PkfG3XrGS0uDea2KBXyoWSR11evTGJiVIyXny3Ih2DkH04qH2T_Ar4kIjcAngPtUnsEVex26tV4QHIrjCq5SlkOdfdAa9Pnl98QVwYH47yO-zlc55bwMgpR2J4fQLyNzWVHNZpH3DbOcHQ3Yenemr6XhM

 

这样我们就完成了简单的WEB API的token验证~

不过这个程序有个问题,如果GetProductById也加上验证那么根据ID获取product的接口 http://localhost:23477/api/products/1 会报错

需要修改成 http://localhost:23477/api/products?id=1 

不知道是哪里出的问题

 

 

本文代码: 

PostMan工具请移步这里看介绍 

转载于:https://www.cnblogs.com/micenote/p/5063835.html

你可能感兴趣的文章
利用循环播放dataurl的视频来防止锁屏:NoSleep.js
查看>>
python3 生成器与迭代器
查看>>
java编写提升性能的代码
查看>>
ios封装静态库技巧两则
查看>>
Educational Codeforces Round 46 (Rated for Div. 2)
查看>>
Abstract Factory Pattern
查看>>
C# 实现Bresenham算法(vs2010)
查看>>
基于iSCSI的SQL Server 2012群集测试(一)--SQL群集安装
查看>>
list 容器 排序函数.xml
查看>>
存储开头结尾使用begin tran,rollback tran作用?
查看>>
Activity启动过程中获取组件宽高的五种方式
查看>>
java导出Excel表格简单的方法
查看>>
SQLite数据库简介
查看>>
利用堆实现堆排序&优先队列
查看>>
Mono源码学习笔记:Console类(四)
查看>>
Android学习路线(十二)Activity生命周期——启动一个Activity
查看>>
《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇03:暂停游戏》
查看>>
CPU,寄存器,一缓二缓.... RAM ROM 外部存储器等简介
查看>>
windows下编译FreeSwitch
查看>>
git .gitignore 文件不起作用
查看>>