asp.net权限认证:OWIN实现OAuth 2.0 之授权码模式(Authorization Code)
授权码模式定义
通过客户端的后台服务器,与“服务提供商”的认证服务器进行认证。
1、用户访问客户端,后者将前者导向认证服务器。
2、用户选择是否给予客户端授权。
3、假设用户给予授权,认证服务器首先生成一个授权码,并返回给用户,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。
4、客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
5、认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。
6、Client拿着access token去访问Resource资源
授权码模式的工作流程图

图 1 (网上搜到的授权码工作流程图说明)
之前看上边的流程图,看了不下10遍,还是搞不懂,这个图真心画的不好理解!
我们一步步来,AuthorizationServer与ResourceServer还是用之前的项目
新建项目:AuthorizationCodeGrant

HomeController.cs也简单
public ActionResult Index()
{
ViewBag.AccessToken = Request.Form["AccessToken"] ?? "";
ViewBag.RefreshToken = Request.Form["RefreshToken"] ?? "";
ViewBag.Action = "";
ViewBag.ResourceResponse = ""; var authorizationServerUri = new Uri("http://localhost:8270/");
var authorizationServer = new AuthorizationServerDescription
{
AuthorizationEndpoint = new Uri(authorizationServerUri, "OAuth/Authorize"),
TokenEndpoint = new Uri(authorizationServerUri, "OAuth/Token")
}; // 刷新AccessToken
var client = new WebServerClient(authorizationServer, "123456", "abcdef");
if (string.IsNullOrEmpty(ViewBag.AccessToken))
{
var authorizationState = client.ProcessUserAuthorization(Request);
if (authorizationState != null)
{
ViewBag.AccessToken = authorizationState.AccessToken;
ViewBag.RefreshToken = authorizationState.RefreshToken;
ViewBag.Action = Request.Path;
}
} // 授权申请
if (!string.IsNullOrEmpty(Request.Form.Get("btnRequestAuthorize")))
{
var grantRequest = client.PrepareRequestUserAuthorization(new[] { "scopes1", "scopes2" });
grantRequest.Send(HttpContext);
Response.End();
} // 申请资源
if (!string.IsNullOrEmpty(Request.Form.Get("btnRequestResource")))
{
var resourceServerUri = new Uri("http://localhost:8001/");
var resourceRequest = new HttpClient(client.CreateAuthorizingHandler(ViewBag.AccessToken));
ViewBag.ResourceResponse = resourceRequest.GetStringAsync(new Uri(resourceServerUri, "api/Values")).Result;
} return View();
}
Index.cshtml
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Authorization Code Grant Client</title>
</head>
<body>
<form id="form1" action="@ViewBag.Action" method="POST">
<div>
<input id="AccessToken" name="AccessToken" value="@ViewBag.AccessToken" type="hidden" />
<input id="Authorize" name="btnRequestAuthorize" value="向认证服务器索要授权" type="submit" />
<input id="Resource" name="btnRequestResource" value="访问资源(Resource)" type="submit" />
</div>
<div>@ViewBag.ResourceResponse</div>
</form>
</body>
</html>
运行项目

授权过程
点击“向认证服务索要授权”,根据HomeController.cs文件的设置,页面预计会跳转到"http://localhost:8270/OAuth/Authorize"
所以我们需要在认证服务中新增处理授权码模式的处理逻辑
在项目AuthorizationServer中新增OAuthController.cs、Authorize.cshtml
public class OAuthController : Controller
{
public ActionResult Authorize()
{
if (Response.StatusCode != 200)
{
return View("AuthorizeError");
} var authentication = HttpContext.GetOwinContext().Authentication;
var ticket = authentication.AuthenticateAsync("Application").Result;
var identity = ticket != null ? ticket.Identity : null;
if (identity == null)
{
authentication.Challenge("Application");
return new HttpUnauthorizedResult(); //用户登录凭证失效就报401错误,并且跳转至AccountController中的Login中
} ViewBag.IdentityName = identity.Name;
ViewBag.Scopes = (Request.QueryString.Get("scope") ?? "").Split(' '); if (Request.HttpMethod == "POST")
{
// 点击btnGrant就确认授权,返回token等信息
if (!string.IsNullOrEmpty(Request.Form.Get("btnGrant")))
{
identity = new ClaimsIdentity(identity.Claims, "Bearer", identity.NameClaimType, identity.RoleClaimType);
foreach (var scope in ViewBag.Scopes)
{
identity.AddClaim(new Claim("urn:oauth:scope", scope));
}
authentication.SignIn(identity);
} if (!string.IsNullOrEmpty(Request.Form.Get("btnOtherLogin")))
{
authentication.SignOut("Application");
authentication.Challenge("Application");
return new HttpUnauthorizedResult();
}
} return View();
}
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Authorize</title>
</head>
<body>
<h1>认证页面</h1>
<form method="POST">
<p>登录用户:@ViewBag.IdentityName</p>
<p>第三方应用需要你给他开放以下权限</p>
<ul>
@foreach (var scope in ViewBag.Scopes)
{
<li>@scope</li>
}
</ul>
<p>
<input type="submit" name="btnGrant" value="确认授权" />
<input type="submit" name="btnOtherLogin" value="以不同用户登录" />
</p>
</form>
</body>
</html>
public class AccountController : Controller
{
public ActionResult Login()
{
var authentication = HttpContext.GetOwinContext().Authentication;
if (Request.HttpMethod == "POST")
{
// 默认用户登录成功
// 生产环境需要单独整合第三方登录信息
var username = Request.Form["username"]; authentication.SignIn(
new AuthenticationProperties { IsPersistent = true },
new ClaimsIdentity(
new[] { new Claim(ClaimsIdentity.DefaultNameClaimType, username) }, "Application"));
} return View();
} public ActionResult Logout()
{
return View();
}
}
运行项目,成功跳转至认证登录页面

点击登录,此时url地址为:
http://localhost:8270/OAuth/Authorize?client_id=123456&redirect_uri=http%3A%2F%2Flocalhost%3A4825%2F&state=IUKeWFTR1HKi4hlzKOOPgw&scope=scopes1%20scopes2&response_type=code
7.1 client_id为客户端ID,即之前我们在AuthorizationCodeGrant项目设置的clientID
7.2 redirect_uri、state为之前登录时就确定的值
7.3 scope为用户确定授权的范围
7.4 response_type=code,即指定为授权码模式

确认授权
此时url有变化:http://localhost:4825/?code=efab38fc30c741a198b20663ec60869a36c6b25ff21f4c9986bcb9c9ae8d20eb&state=tjB9jXhNiHvIr4Ko9VhEkw

注意:这一步会会默认获取Token


点击访问资源

完全能够对上;
url中的code即认证服务返回的授权码,之后Client请求Token会用这个code来交换
这个就是授权码模式的特色的地方了

自此,整个授权码模式已经完毕了哦
asp.net权限认证系列
- asp.net权限认证:Forms认证
- asp.net权限认证:HTTP基本认证(http basic)
- asp.net权限认证:Windows认证
- asp.net权限认证:摘要认证(digest authentication)
- asp.net权限认证:OWIN实现OAuth 2.0 之客户端模式(Client Credential)
- asp.net权限认证:OWIN实现OAuth 2.0 之密码模式(Resource Owner Password Credential)
- asp.net权限认证:OWIN实现OAuth 2.0 之授权码模式(Authorization Code)
- asp.net权限认证:OWIN实现OAuth 2.0 之简化模式(Implicit)
asp.net权限认证:OWIN实现OAuth 2.0 之授权码模式(Authorization Code)的更多相关文章
- 基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】
之前已经简单实现了OAUTH2的授权码模式(Authorization Code),但是基于JAVA的,今天花了点时间调试了OWIN的实现,基本就把基于OWIN的OAUHT2的四种模式实现完了.官方推 ...
- OAuth 2.0之授权码模式
转载自:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html OAuth 2.0授权码模式 授权码模式(authorization code)是功 ...
- OAuth 第三方登录授权码(authorization code)方式的小例子
假如上面的网站A,可以通过GitHub账号登录: 下面以OAuth其中一种方式,授权码(authorization code)方式为例. 一.第三方登录的原理 所谓第三方登录,实质就是 OAuth 授 ...
- asp.net权限认证:OWIN实现OAuth 2.0 之客户端模式(Client Credential)
asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...
- asp.net权限认证:OWIN实现OAuth 2.0 之密码模式(Resource Owner Password Credential)
asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...
- asp.net权限认证:OWIN实现OAuth 2.0 之简化模式(Implicit)
asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...
- asp.net权限认证:Windows认证
asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...
- asp.net权限认证:Forms认证
asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...
- asp.net权限认证:HTTP基本认证(http basic)
asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...
随机推荐
- JavaScript(二)---- 变量、数据类型和运算符
变量 javaScript中的变量变量是弱类型的,用var来声明. javascript的变量声明格式: var 变量名 = 数据; 声明变量要注意的事项: 1. 在javascript中声明变量是 ...
- 在Action类中获得HttpServletResponse对象的四种方法
在struts1.xAction类的execute方法中,有四个参数,其中两个就是response和request.而在Struts2中,并没有任何参数,因此,就不能简单地从execute方法获得Ht ...
- Java Base64、AES、SHA1、MD5加密算法(转载)
package com.example.decript; import java.io.UnsupportedEncodingException; import java.security.Inval ...
- .htaccess 使用大全
重新和重定向 注意:首先需要服务器安装和启用mod_rewrite模块. 强制 www RewriteEngine on RewriteCond %{HTTP_HOST} ^example\.com ...
- iOS开发——pch文件创建
新换的公司,接手的项目里面连pch文件都没有,每次需要用到屏幕的宽高时,都是现写.今天既然碰到了,就把PCH这个玩意说一下. 1.Command+N,打开新建文件窗口:iOS->Other-&g ...
- listen函数里面backlog的意义以及各种情况
先看了这篇: http://www.cppblog.com/thisisbin/archive/2010/02/07/107444.html 里面说了会维护两个队列,established 和 syn ...
- 10天学会phpWeChat——第九天:数据库增、删、改、查(CRUD)操作
数据库的操作(CRUD)是一个现代化计算机软件的核心,尤其针对web应用软件.虽然在前面的几讲里,我们针对数据库操作大致有了一些了解,但今天我们需要再次强化下. 除了新瓶装老酒,我们今天还引入一个新的 ...
- WCF不用证书实现验证(messageheader)
上文WCF进阶:将消息正文Base64编码中介绍了实现自定义MessageInspector来记录消息和实现自定义Formatter来改写消息,本文介绍一下在WCF中使用SoapHeader进行验证的 ...
- IOS开发-ObjC-对象、封装
C语言是基于过程的一种编程语言,而OC语言是基于对象的一种语言. C是和其他的面向对象的语言的区别在于C语言更注重地层操作,思维方式相比面向对象的语言而言更接近机器的思维方式,而面向对象的语言更接近于 ...
- c++初学(电梯实验加强版)
Elevator.h class Elevator{public: Elevator(); ~Elevator(); void getNowNum(); void Se ...