使用ASP.NET Identity 實現WebAPI接口的Oauth身份驗證


使用ASP.NET Identity 實現WebAPI接口的Oauth身份驗證

 

目前WEB 前后端分離的開發模式比較流行,之前做過的幾個小項目也都是前后分離的模式,后端使用asp.net webapi 提供restful風格的數據接口;前端主要使用angularjs等框架。在這種前后分離的模式中如何保護我們的數據接口不被非法調用,這就可要考慮到后台接口的身份驗證。我們常用采用的身份驗證有http基本認證(結合https)、http摘要認證、oauth認證等等。本次我們討論的是Oauth認證。

Oauth(Open Authorization)認證:oauth協議為用戶資源的授權提供了一個安全的、開放而又簡易的標准。與以往的授權方式不同之處是OAUTH的授權不會使第三方觸及到用戶的帳號信息(如用戶名與密碼)。

相關學習資料:https://oauth.net/2/

              http://blog.jobbole.com/49211/

              http://kb.cnblogs.com/page/189153/

OWIN (open web interface for .net) :基於.net平台的開放web接口。OWIN 在 .NET Web 服務器和 .NET Web 應用之間定義了一套標准的接口, 其目的是為了實現服務器與應用之間的解耦。

相關學習資料:http://owin.org/

              http://www.cnblogs.com/zergcom/tag/OWIN/

              http://www.nmtree.net/2014/06/13/getting-started-with-owin-and-katana.html

ASP.NET Identity: asp.net身份驗證框架,微軟在MVC 5.0(.NET Framework4.5)中新引入,類似mumbership。

相關學習資料:https://www.asp.net/identity

              http://www.cnblogs.com/liuhaorain/p/3776467.html

              http://www.cnblogs.com/shanyou/p/3918178.html

              http://www.cnblogs.com/vxchin/p/introduction-to-aspnet-identity.html

 

一、用VS2015新建一個項目,項目類型選擇“ASP.NET web應用程序”點擊“確定”(圖1),選擇“Web API”作為模板,點擊“確定”(圖2)。

 

 

圖1

 

 

圖2

二、使用Nuget安裝:Microsoft.AspNet.WebApi.Owin(圖3)、Microsoft.Owin.Host.SystemWeb(圖4

 

 

 

 

圖3

 

 

 

圖4

 

三、添加Owin啟動類(圖5):

設置Startup類代碼如下:

 

using System.Web.Http;

using Microsoft.Owin;

using Owin;

 

[assembly: OwinStartup(typeof(WebAPI.Startup))]

namespace WebAPI

{

    public class Startup

    {

        public void Configuration(IAppBuilder app)

        {

            HttpConfiguration config = new HttpConfiguration();

            WebApiConfig.Register(config);

            app.UseWebApi(config);

        }

    }

}

 

 

 

圖5

 

四、刪除Global.asax

 

五、修改App_Start文件夾中的WebApiConfig.cs文件,實現api數據通過json格式返回(圖6):

 

var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();

jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

 

 

 

圖6

 

六、安裝Microsoft.AspNet.Identity.Owin、Microsoft.AspNet.Identity.EntityFramework

 

 

 

圖7

 

 

 

圖8

 

七、創建AuthContext.cs: 

 

using Microsoft.AspNet.Identity.EntityFramework;

 

namespace WebAPI

{

    public class AuthContext: IdentityDbContext<IdentityUser>

    {

        public AuthContext() : base("AuthDataBase")

        { }

    }

}

 

Web.config中增加connectionString:

 

<connectionStrings>

    <add name="AuthDataBase" connectionString="Data Source=.\sqlexpress;Initial Catalog= AuthDataBase;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />

  </connectionStrings>

 

八、在Models文件夾中創建UserModel.cs

 

using System.ComponentModel.DataAnnotations;

 

namespace WebApp.Models

{

    public class UserModel

    {

        [Required]

        [Display(Name = "User Name")]

        public string UserName { get; set; }

        [Required]

        [DataType(DataType.Password)]

        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long", MinimumLength = 6)]

        public string Password { get; set; }

    }

}

 

九、添加AuthRepository.cs:

 

using System;

using System.Threading.Tasks;

using Microsoft.AspNet.Identity;

using Microsoft.AspNet.Identity.EntityFramework;

using WebAPI.Models;

 

namespace WebAPI

{

    public class AuthRepository : IDisposable

    {

        private AuthContext _ctx;

        private UserManager<IdentityUser> _userManager;

        public AuthRepository()

        {

            _ctx = new AuthContext();

            _userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(_ctx));

        }

        public async Task<IdentityResult> Register(UserModel model)

        {

            IdentityUser user = new IdentityUser()

            {

                UserName = model.UserName

            };

 

            IdentityResult result = await _userManager.CreateAsync(user, model.Password);

 

            return result;

        }

        public async Task<IdentityUser> FindUser(UserModel model)

        {

            IdentityUser user = await _userManager.FindAsync(model.UserName, model.Password);

 

            return user;

        }

        public async Task<IdentityUser> FindUserByName(string username)

        {

            IdentityUser user = await _userManager.FindByNameAsync(username);

            return user;

        }

        public void Dispose()

        {

            _ctx.Dispose();

            _userManager.Dispose();

        }

    }

}

 

十、添加AccountController.cs

 

using System.Threading.Tasks;

using System.Web.Http;

using Microsoft.AspNet.Identity;

using WebAPI.Models;

 

namespace WebAPI.Controllers

{

    [Authorize]

    [RoutePrefix("api/Account")]

    public class AccountController : ApiController

    {

 

        private AuthRepository _authRepo;

        public AccountController()

        {

            _authRepo = new AuthRepository();

        }

        [AllowAnonymous]

        [Route("Register")]

        public async Task<IHttpActionResult> Register(UserModel model)

        {

            if (!ModelState.IsValid)

            {

                return BadRequest(ModelState);

            }

            IdentityResult result = await _authRepo.Register(model);

            IHttpActionResult errorResult = GetError(result);

            if (errorResult != null)

            {

                return errorResult;

            }

            return Ok();

        }

 

        private IHttpActionResult GetError(IdentityResult result)

        {

            if (result == null)

            {

                return InternalServerError();

            }

            if (!result.Succeeded)

            {

                foreach (string err in result.Errors)

                {

                    ModelState.AddModelError("", err);

                }

                if (ModelState.IsValid)

                {

                    return BadRequest();

                }

                return BadRequest(ModelState);

            }

            return null;

        }

 

    }

}

 

 

十一、使用Fiddler調用接口http://localhost:17933/api/account/register(圖9)。調用成功后會生成數據庫AuthDataBase和用戶相關表(圖10)

POST http://localhost:17933/api/account/register

 

Header

Content-Type: application/x-www-form-urlencoded

 

Request Body

UserName=admin&Password=111111

 

圖9

 

 

圖10

 

十二、添加OrderController.cs:

 

using System;

using System.Collections.Generic;

using System.Web.Http;

 

namespace WebAPI.Controllers

{

    public class OrderController : ApiController

    {

        [Authorize]

        [RoutePrefix("api/orders")]

        public class OrdersController : ApiController

        {

            [Route]

            public IHttpActionResult Get()

            {

                return Ok(Order.CreateOrders());

            }

        }

        public class Order

        {

            public int OrderID { get; set; }

            public string CustomerName { get; set; }

            public string ShipperCity { get; set; }

            public Boolean IsShipped { get; set; }

 

            public static List<Order> CreateOrders()

            {

                List<Order> OrderList = new List<Order>

            {

                new Order {OrderID = 10248, CustomerName = "Taiseer Joudeh", ShipperCity = "Amman", IsShipped = true },

                new Order {OrderID = 10249, CustomerName = "Ahmad Hasan", ShipperCity = "Dubai", IsShipped = false},

                new Order {OrderID = 10250,CustomerName = "Tamer Yaser", ShipperCity = "Jeddah", IsShipped = false },

                new Order {OrderID = 10251,CustomerName = "Lina Majed", ShipperCity = "Abu Dhabi", IsShipped = false},

                new Order {OrderID = 10252,CustomerName = "Yasmeen Rami", ShipperCity = "Kuwait", IsShipped = true}

            };

                return OrderList;

            }

        }

    }

}

 

 

十三、安裝Microsoft.Owin.Security.OAuth(OAuth Bearer Token支持類庫 )(圖11)

 

 

 

圖11

 

 

十四、添加Providers文件夾,在文件夾中創建AuthorizationServerProvider.cs

 

using System.Security.Claims;

using System.Threading.Tasks;

using Microsoft.AspNet.Identity.EntityFramework;

using Microsoft.Owin.Security.OAuth;

using WebAPI.Models;

 

namespace WebAPI.Providers

{

    public class AuthorizationServerProvider : 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(

                    new UserModel() { UserName = context.UserName, Password = context.Password });

                if (user == null)

                {

                    context.SetError("invalid_grant", "The username 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);

        }

    }

}

 

安裝:Microsoft.Owin.Cors (跨域)(圖12)

 

 

 

圖12

 

修改Startup.cs:

 

using System;

using System.Web.Http;

using Microsoft.Owin;

using Microsoft.Owin.Cors;

using Microsoft.Owin.Security.OAuth;

using Owin;

using WebAPI.Providers;

 

[assembly: OwinStartup(typeof(WebAPI.Startup))]

 

namespace WebAPI

{

    public class Startup

    {

        public void Configuration(IAppBuilder app)

        {

            HttpConfiguration config = new HttpConfiguration();

            ConfigAuth(app);

            WebApiConfig.Register(config);

            app.UseCors(CorsOptions.AllowAll);

            app.UseWebApi(config);

        }

 

        public void ConfigAuth(IAppBuilder app)

        {

            OAuthAuthorizationServerOptions option = new OAuthAuthorizationServerOptions()

            {

                AllowInsecureHttp = true,

                TokenEndpointPath = new PathString("/token"),

                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),

                Provider = new AuthorizationServerProvider()

            };

 

            app.UseOAuthAuthorizationServer(option);

            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

        }

    }

}

 

 

十五、使用fiddler調用:http://localhost:17933/token(圖13),調用成功后生成token(圖14

POST http://localhost:17933/token

Header

Content-Type: application/x-www-form-urlencoded

Request Body

grant_type=password&UserName=admin&Password=111111

 

 

圖13

 

 

圖14

 

十六、使用上一步驟生成的token請求order數據(圖15),請求成功后返回Order數據(圖16):

 

GET  http://localhost:17933/api/orders

Header

Authorization: bearer dJvGpKGVPUfJMW_lkcMY79lEV57-LgRe1sZ35OKCzhIHsTaRGBenZ_2--GtosTbrbnwnHMyNKK_f-NalQtgXP_kwx5gj48KnzSaKcTBulQqPP2kFpB6Gbc4npQQmFttJwogEwH3a7-99PsH07Tjl-lbbVvMNhNzGEhK36e5AgeI0yyjIa2JnZGF1kujCj_hrnLvUrazgl6kvmPQZFXXgczuVWnL9dXZe4XMgg0pQ2sI

 

 

 

 

圖15

 

 

 

 

圖16


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM