ASP.NET Web API 2基於令牌的身份驗證

基於令牌的認證html

    咱們知道WEB網站的身份驗證通常經過session或者cookie完成的,登陸成功後客戶端發送的任何請求都帶上cookie,服務端根據客戶端發送來的cookie來識別用戶。api

    WEB API使用這樣的方法不是很適合,因而就有了基於令牌的認證,使用令牌認證有幾個好處:可擴展性、鬆散耦合、移動終端調用比較簡單等等,別人都用上了,你還有理由不用嗎?安全

    下面咱們花個20分鐘的時間來實現一個簡單的WEB API token認證:cookie

 

Step 1: 新建一個空的WEB API項目,項目名稱就設置爲WebApisession

 

Step 2: 在Models目錄下新建一個 Product 類 :app

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 類async

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<Product> 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<Product> GetProductsByCategory(string category)
        {
            return products.Where(p => string.Equals(p.Category, category,
                    StringComparison.OrdinalIgnoreCase));
        }
    }
}

F5運行後就能夠使用這個簡單的WebApi了,測試api能夠使用Postman工具:ide

    獲取全部數據  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.2
Install-Package Microsoft.Owin.Host.SystemWeb -Version 2.1.0
Install-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<Product> 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<Product> 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 

不知道是哪裏出的問題

 

 

本文代碼: http://pan.baidu.com/s/1jGxZVKU

PostMan工具請移步這裏看介紹 http://www.cnblogs.com/wade-xu/p/4228954.html

相關文章
相關標籤/搜索