zoukankan      html  css  js  c++  java
  • 基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】

    之前已经简单实现了OAUTH2的授权码模式(Authorization Code),但是基于JAVA的,今天花了点时间调试了OWIN的实现,基本就把基于OWIN的OAUHT2的四种模式实现完了。官方推荐的.NET 包有

    Katana已经不更新了,新的版本是已经是asp.net core 1.0的一部分,实现OAUTH2好的选择可以考虑使用新版IdentityServer3对应asp.net core 1.0版本为IdentityServer4。

    Startup

    public partial class Startup
        {
            private readonly ConcurrentDictionary<string, string> _authenticationCodes = new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
            public void ConfigureAuth(IAppBuilder app)
            {
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = Paths.AuthenticationType,
                    AuthenticationMode = AuthenticationMode.Passive,
                    LoginPath = new PathString(Paths.LoginPath),
                    LogoutPath = new PathString(Paths.LogoutPath),
                });
    
                app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
                {
                    AuthorizeEndpointPath = new PathString(Paths.AuthorizePath),
                    TokenEndpointPath = new PathString(Paths.TokenPath),
                    AccessTokenExpireTimeSpan = TimeSpan.FromHours(2),
                    Provider = new OAuthAuthorizationServerProvider
                    {
                        OnValidateClientRedirectUri = ValidateClientRedirectUri,
                        OnValidateClientAuthentication = ValidateClientAuthentication,
                        OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
                        OnGrantClientCredentials = GrantClientCredetails
                    },
                    //Provider = new ApplicationOAuthProvider(),
                    AuthorizationCodeProvider = new AuthenticationTokenProvider
                    {
                        OnCreate = CreateAuthenticationCode,
                        OnReceive = ReceiveAuthenticationCode,
                    },
                    RefreshTokenProvider = new AuthenticationTokenProvider
                    {
                        OnCreate = CreateRefreshToken,
                        OnReceive = ReceiveRefreshToken,
                    },
                    ApplicationCanDisplayErrors = true,
    #if DEBUG
                    //HTTPS is allowed only AllowInsecureHttp = false
                    AllowInsecureHttp = true,
    #endif
                });
            }
    
            private void CreateAuthenticationCode(AuthenticationTokenCreateContext context)
            {
                context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n"));
                _authenticationCodes[context.Token] = context.SerializeTicket();
            }
    
            private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
            {
                string value;
                if (_authenticationCodes.TryRemove(context.Token, out value))
                {
                    context.DeserializeTicket(value);
                }
            }
    
            private Task GrantClientCredetails(OAuthGrantClientCredentialsContext context)
            {
                var identity = new ClaimsIdentity(new GenericIdentity(context.ClientId, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
                context.Validated(identity);
                return Task.FromResult(0);
            }
    
            private Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
            {
                var identity = new ClaimsIdentity(new GenericIdentity(context.UserName, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
                context.Validated(identity);
                return Task.FromResult(0);
            }
    
            private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
            {
                string clientId;
                string clientSecret;
                if (context.TryGetBasicCredentials(out clientId, out clientSecret) || context.TryGetFormCredentials(out clientId, out clientSecret))
                {
                    context.Validated();
                }
                return Task.FromResult(0);
            }
    
            private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
            {
                if (context.ClientId == Clients.Client1.Id)
                {
                    context.Validated();
                    //context.Validated(Clients.Client1.RedirectUrl);
                }
                else if (context.ClientId == Clients.Client2.Id)
                {
                    context.Validated(Clients.Client2.RedirectUrl);
                }
                return Task.FromResult(0);
            }
    
    
            private void CreateRefreshToken(AuthenticationTokenCreateContext context)
            {
                context.SetToken(context.SerializeTicket());
            }
    
            private void ReceiveRefreshToken(AuthenticationTokenReceiveContext context)
            {
                context.DeserializeTicket(context.Token);
            }
        }

    OAuthController

    /// <summary>
            /// 授权码模式授权
            /// </summary>
            /// <returns></returns>
            public ActionResult Authorize()
            {
                var authentication = HttpContext.GetOwinContext().Authentication;
                var ticket = authentication.AuthenticateAsync(Paths.AuthenticationType).Result;
                var identity = ticket != null ? ticket.Identity : null;
                if (identity == null)
                {
                    authentication.Challenge(Paths.AuthenticationType);
                    return new HttpUnauthorizedResult();
                }
                var scopes = (Request.QueryString.Get("scope") ?? "").Split(' ');
                if (Request.HttpMethod == "POST")
                {
                    if (!string.IsNullOrEmpty(Request.Form.Get("submit.Grant")))
                    {
                        identity = new ClaimsIdentity(identity.Claims, "Bearer", identity.NameClaimType, identity.RoleClaimType);
                        foreach (var scope in scopes)
                        {
                            identity.AddClaim(new Claim("urn:oauth:scope", scope));
                        }
                        authentication.SignIn(identity);
                    }
                    if (!string.IsNullOrEmpty(Request.Form.Get("submit.Login")))
                    {
                        authentication.SignOut("Application");
                        authentication.Challenge("Application");
                        return new HttpUnauthorizedResult();
                    }
                }
                return View();
            }

    AccountController

    /// <summary>
            /// 用户登录
            /// </summary>
            /// <returns></returns>
            public ActionResult Login()
            {
                var authentication = HttpContext.GetOwinContext().Authentication;
                if (Request.HttpMethod == "POST")
                {
                    var isPersistent = !string.IsNullOrEmpty(Request.Form.Get("isPersistent"));
                    if (!string.IsNullOrEmpty(Request.Form.Get("submit.Signin")))
                    {
                        authentication.SignIn(
                            new AuthenticationProperties { IsPersistent = isPersistent },
                            new ClaimsIdentity(new[] { new Claim(ClaimsIdentity.DefaultNameClaimType, Request.Form["username"]) }, "Application"));
                    }
                }
                return View();
            }
    
            /// <summary>
            /// 退出
            /// </summary>
            /// <returns></returns>
            public ActionResult Logout()
            {
                return View();
            }

    调试

    获得授权码
    GET /oauth/authorize?client_id=irving&redirect_uri=
    http://localhost:38500/oauth_callback&state=LYUVwcuaGuKeRTjxhdFzhQ&scope=bio

    %20notes&response_type=code HTTP/1.1

    http://localhost:56889/oauth/authorize?

    client_id=irving&redirect_uri=http://localhost:38500/oauth_callback&state=LYUVwcuaGuKeRTjxhdFzhQ&scope=bio%20notes&response_type=code

    页面重定向
    HTTP/1.1 302 Found
    Location: /oauth_callback?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz

    http://localhost:56889/oauth_callback?code=0aa3e35bd515413bb93bdb6fb015591cc763a8d30c554730a07ebd39e3149252&state=LYUVwcuaGuKeRTjxhdFzhQ


    获得令牌
    POST /token HTTP/1.1
    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded

    grant_type=authorization_code&code=929dc42905a24e79bdf028f7043769acddd90056ca8141708b3834ec174e8083&state=LYUVwcuaGuKeRTjxhdFzhQ&redirect_uri=http://localhost:38500/oauth_callback

    源码:https://github.com/zhouyongtao/SecuringForWebAPI/tree/master/KatanaForWebAPI

    注意事项

    资源服务器识别认证服务器颁发的令牌, 需要配置相同的machinekey

    <machineKey decryptionKey="B7EFF1C5839A624E3F97D0268917EDE82F408D2ECBFAC817" validation="SHA1" validationKey="C2B8DF31AB9624D69428066DFDA1A479542825F3B48865C4E47AF6A026F22D853DEC2B3248DF268599BF89EF78B9E86CA05AC73577E0D5A14C45E0267588850B" />

    REFER:
    http://beginor.github.io/2015/01/24/oauth2-server-with-owin.html
    http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server

  • 相关阅读:
    ros 使用命令测试topic
    python unicode
    python ros 回充demo
    python ros 回充调用demo
    flask报错No module named 'flask.ext'
    python flask 接口
    ros 安装c++编译的可执行文件
    Linux-Ubuntu14.04下mongodb安装部署
    如何在Ubuntu 14.04中安装最新版Eclipse
    ubuntu 14.04 安装redis5.0.3
  • 原文地址:https://www.cnblogs.com/Irving/p/5220578.html
Copyright © 2011-2022 走看看