使用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

使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证的更多相关文章

  1. ASP.NET MVC对WebAPI接口操作(添加,更新和删除)

    昨天<怎样操作WebAPI接口(显示数据)>http://www.cnblogs.com/insus/p/5670401.html 既有使用jQuery,也有使作HttpClient来从数 ...

  2. 如何基于asp.net core的Identity框架在mysql上作身份验证处理

    首先了解这个概念,我一开始也是理解和掌握基本的概念,再去做程序的开发.Identity框架是微软自己提供,基于.net core平台,可拓展.轻量 级.面向多个数据库的身份验证框架.IdentityS ...

  3. ASP.NET Web API 2基于令牌的身份验证

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

  4. Asp.Net Core 5 REST API 使用 JWT 身份验证 - Step by Step

    翻译自 Mohamad Lawand 2021年1月22日的文章 <Asp Net Core 5 Rest API Authentication with JWT Step by Step> ...

  5. 使用ASP.NET Identity以手机短信实现双重验证

    这篇文章将展示怎么使用SMS短信启动双重验证 创建一个ASP.NET 5项目 一开始,使用Visual studio 2015创建一个新的ASP.NET Web应用程序: 在下一步中选择ASP.NET ...

  6. ASP.NET Core 如何用 Cookie 来做身份验证

    前言 本示例完全是基于 ASP.NET Core 3.0.本文核心是要理解 Claim, ClaimsIdentity, ClaimsPrincipal,读者如果有疑问,可以参考文章 理解ASP.NE ...

  7. ASP.NET没有魔法——ASP.NET Identity 的“多重”身份验证

    ASP.NET Identity除了提供基于Cookie的身份验证外,还提供了一些高级功能,如多次输入错误账户信息后会锁定用户禁止登录.集成第三方验证.账户的二次验证等,并且ASP.NET MVC的默 ...

  8. 介绍 ASP.NET Identity - ASP.NET 应用程序的成员身份认证系统

    ASP.NET Identity 是构建 ASP.NET web 应用程序的一种新的身份认证系统.ASP.NET Identity 可以让您的应用程序拥有登录功能,并可以轻松地自定义登录用户的相关数据 ...

  9. ASP.NET Identity入门系列教程(一) 初识Identity

    摘要 通过本文你将了解ASP.NET身份验证机制,表单认证的基本流程,ASP.NET Membership的一些弊端以及ASP.NET Identity的主要优势. 目录 身份验证(Authentic ...

随机推荐

  1. Dart 语言了解

    Dart 语言了解 概念 当您了解Dart语言时,请记住以下事实和概念: 您可以放在变量中的所有内容都是一个对象,每个对象都是一个类的实例.偶数,函数和 null对象.所有对象都从Object类继承. ...

  2. Backbone.js Basics: Bringing an App to Life with Events

    http://www.sitepoint.com/backbone-basics-events/

  3. 20155210 潘滢昊 Java第三次实验

    Java第三次实验 实验内容 在IDEA中使用工具(Code->Reformate Code)把代码重新格式化 在码云上把自己的学习搭档加入自己的项目中,确认搭档的项目加入自己后,下载搭档实验二 ...

  4. 2017 ACM-ICPC 亚洲区(西安赛区)网络赛

    A There is a tree with nn nodes, at which attach a binary 64*6464∗64 matrix M_i (1 \le i \le n)M ​i ...

  5. 20155336 《Java程序设计》实验二 (Java面向对象程序设计)实验报告

    20155336 <Java程序设计>实验二 (Java面向对象程序设计)实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉 ...

  6. 【转载】C/C++杂记:运行时类型识别(RTTI)与动态类型转换原理

    原文:C/C++杂记:运行时类型识别(RTTI)与动态类型转换原理 运行时类型识别(RTTI)的引入有三个作用: 配合typeid操作符的实现: 实现异常处理中catch的匹配过程: 实现动态类型转换 ...

  7. RHCSA day5

    4.调整逻辑卷容量 请按照以下要求调整本地逻辑卷lvm1的容量: 调整后的逻辑卷及文件系统大小为770MiB 调整后确保文件系统中已存在的内容不能被破坏 调整后的容量可能出现误差,只要在730MiB ...

  8. MSP430的CAN通信发送

    1. 电路图如下,RE是接收使能,DE是发送使能,看图的话,这个CAN只支持半双工 2. 使用MSP430F149,以下代码只有发送,其实用的是串口 #include <msp430x14x.h ...

  9. php编程知识点2018

    一 .PHP基础部分 1.PHP语言的一大优势是跨平台,什么是跨平台? PHP的运行环境最优搭配为Apache+MySQL+PHP,此运行环境可以在不同操作系统(例如windows.Linux等)上配 ...

  10. Django模型层:单表操作

    一 ORM简介 查询数据层次图解:如果操作mysql,ORM是在pymysq之上又进行了一层封装