首页 > Windows开发 > 详细

asp.net权限认证:OWIN实现OAuth 2.0 之授权码模式(Authorization Code)

时间:2017-02-01 23:35:34      阅读:1125      评论:0      收藏:0      [点我收藏+]

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)

 

授权码模式定义:用户向客户端提供用户名密码。客户端使用这些信息,向“服务提供商” 进行认证。

先上密码模式的工作流程图:

技术分享

图 1 (网上搜到的授权码流程图说明)

 

之前看上边的流程图,看了不下10遍,还是搞不懂,这个图真心画的不好理解!

我们一步步来,AuthorizationServer与ResourceServer还是用之前的项目

1、新建项目:AuthorizationCodeGrant

技术分享

 

2、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();
        }

3、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>

4、运行项目  

技术分享

5、点击“向认证服务索要授权”,根据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(); } }

 

6、OK,运行项目看看,成功跳转至认证登录页面

技术分享

7、点击登录,此时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,即指定为授权码模式

技术分享

8、确认授权

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

技术分享

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

技术分享

技术分享

 

9、点击访问资源

技术分享

 

10、完全能够对上;

url中的code即认证服务返回的授权码,之后Client请求Token会用这个code来交换

这个就是授权码模式的特色的地方了

 技术分享

 

 自此,整个授权码模式已经完毕了哦

 

asp.net权限认证:OWIN实现OAuth 2.0 之授权码模式(Authorization Code)

原文:http://www.cnblogs.com/lanxiaoke/p/6360466.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!