使用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
使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证的更多相关文章
- ASP.NET MVC对WebAPI接口操作(添加,更新和删除)
昨天<怎样操作WebAPI接口(显示数据)>http://www.cnblogs.com/insus/p/5670401.html 既有使用jQuery,也有使作HttpClient来从数 ...
- 如何基于asp.net core的Identity框架在mysql上作身份验证处理
首先了解这个概念,我一开始也是理解和掌握基本的概念,再去做程序的开发.Identity框架是微软自己提供,基于.net core平台,可拓展.轻量 级.面向多个数据库的身份验证框架.IdentityS ...
- ASP.NET Web API 2基于令牌的身份验证
基于令牌的认证 我们知道WEB网站的身份验证一般通过session或者cookie完成的,登录成功后客户端发送的任何请求都带上cookie,服务端根据客户端发送来的cookie来识别用户. WEB A ...
- 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> ...
- 使用ASP.NET Identity以手机短信实现双重验证
这篇文章将展示怎么使用SMS短信启动双重验证 创建一个ASP.NET 5项目 一开始,使用Visual studio 2015创建一个新的ASP.NET Web应用程序: 在下一步中选择ASP.NET ...
- ASP.NET Core 如何用 Cookie 来做身份验证
前言 本示例完全是基于 ASP.NET Core 3.0.本文核心是要理解 Claim, ClaimsIdentity, ClaimsPrincipal,读者如果有疑问,可以参考文章 理解ASP.NE ...
- ASP.NET没有魔法——ASP.NET Identity 的“多重”身份验证
ASP.NET Identity除了提供基于Cookie的身份验证外,还提供了一些高级功能,如多次输入错误账户信息后会锁定用户禁止登录.集成第三方验证.账户的二次验证等,并且ASP.NET MVC的默 ...
- 介绍 ASP.NET Identity - ASP.NET 应用程序的成员身份认证系统
ASP.NET Identity 是构建 ASP.NET web 应用程序的一种新的身份认证系统.ASP.NET Identity 可以让您的应用程序拥有登录功能,并可以轻松地自定义登录用户的相关数据 ...
- ASP.NET Identity入门系列教程(一) 初识Identity
摘要 通过本文你将了解ASP.NET身份验证机制,表单认证的基本流程,ASP.NET Membership的一些弊端以及ASP.NET Identity的主要优势. 目录 身份验证(Authentic ...
随机推荐
- mysql底层实现
MySQL 的常用引擎 1. InnoDB InnoDB 的存储文件有两个,后缀名分别是 .frm 和 .idb,其中 .frm 是表的定义文件,而 idb 是数据文件. InnoDB 中存在表锁和行 ...
- ajax渲染swiper问题
由于ajax异步请求的关系,所以之前将swiper初始化写在请求外面时总是不能达到效果.下面是能正常渲染的效果示例: $http({ method:"GET", url:" ...
- CentOS7和OpenStack的笔记(一)
CentOS7和OpenStack的笔记(一) 最近搞CentOS7系统和OpenStack框架,整了近一个星期,系统装了好几次,框架搭了又从搭.虽然最后的实例没能启动成功,但是在这专研的一个星期里, ...
- OpenFlow1.3.3 学习记录(持续更新)
OpenFlow1.3.3 学习记录(持续更新) 正在学习OpenFlow1.3,该篇笔记将日常更新,主要内容大致为官方文档的总结与翻译. 交换机组件 按照优先级顺序进行包匹配,如果匹配到流表项,则执 ...
- 计算机专业C语言编程学习重点:指针化难为易
C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...
- od源代码
```/* od -- dump files in octal and other formats Copyright (C) 92, 1995-2002 Free Software Foundati ...
- 【LG4103】[HEOI2014]大工程
[LG4103][HEOI2014]大工程 题面 洛谷 题解 先建虚树,下面所有讨论均是在虚树上的. 对于第一问:直接统计所有树边对答案的贡献即可. 对于第\(2,3\)问:记\(f[x]\)表示在\ ...
- 解决WCF传输的数据量过大问题
今天写了个WCF接口,然后自测通过,和别人联调时报 远程服务器返回错误: (413) Request Entity Too Large 错误!记得以前写的时候也出现过这个错误,大致解决办 ...
- 04-JVM内存模型:直接内存
1.1.什么是直接内存(Derect Memory) 在内存模型最开始的章节中,我们画出了JVM的内存模型,里面并不包含直接内存,也就是说这块内存区域并不是JVM运行时数据区的一部分,但它却会被频繁的 ...
- Appium+python HTML测试报告(1)(转)
(原文:https://www.cnblogs.com/fancy0158/p/10054632.html) 测试任务执行完成后,我们需要一份通俗易懂的测试报告来展示自动化测试的结果. HTMLTes ...