• 基于Owin Oauth2构建授权服务器


    ---恢复内容开始---

    我们简单的描述怎么通过owin和asp.net mvc创建一个授权服务器,首先创建一个空的MVC网站名为AuthorizationServer并且安装如下包:

    • Microsoft.AspNet.Mvc
    • Microsoft.Owin.Host.SystemWeb
    • Microsoft.Owin.Security.OAuth
    • Microsoft.Owin.Security.Cookies

    在项目的根目录创建一个名为Startup的类:

    using Microsoft.Owin;
    using Owin;
    
    [assembly: OwinStartup(typeof(AuthorizationServer.Startup))]
    
    namespace AuthorizationServer
    {
       public partial class Startup
       {
          public void Configuration(IAppBuilder app)
          {
             ConfigureAuth(app);
          }
       }
    }

    创建一个App_Start文件夹,选中App_Start添加类文件Startup.Auth.cs

    public void ConfigureAuth(IAppBuilder app)
     {
         // 启用登录应用使用Cookie
         app.UseCookieAuthentication(new CookieAuthenticationOptions
         {
             AuthenticationType = "Application",
             AuthenticationMode = AuthenticationMode.Passive,
             LoginPath = new PathString(Paths.LoginPath),
             LogoutPath = new PathString(Paths.LogoutPath),
         });
    
         // 启用外部登录使用Cookie
         app.SetDefaultSignInAsAuthenticationType("External");
         app.UseCookieAuthentication(new CookieAuthenticationOptions
         {
             AuthenticationType = "External",
             AuthenticationMode = AuthenticationMode.Passive,
             CookieName = CookieAuthenticationDefaults.CookiePrefix + "External",
             ExpireTimeSpan = TimeSpan.FromMinutes(5),
         });
    
         // 启用google身份验证
         app.UseGoogleAuthentication();
    
         // 配置授权服务
         app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
         {
             AuthorizeEndpointPath = new PathString(Paths.AuthorizePath),
             TokenEndpointPath = new PathString(Paths.TokenPath),
             ApplicationCanDisplayErrors = true,
    #if DEBUG
                    AllowInsecureHttp = true,
    #endif
         // 授权服务提供者控制授权服务的生命周期
         Provider = new OAuthAuthorizationServerProvider
         {
             OnValidateClientRedirectUri = ValidateClientRedirectUri,
             OnValidateClientAuthentication = ValidateClientAuthentication,
             OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
             OnGrantClientCredentials = GrantClientCredetails
         },
    
         // 授权码提供者用来创建和接受授权码
         AuthorizationCodeProvider = new AuthenticationTokenProvider
         {
             OnCreate = CreateAuthenticationCode,
             OnReceive = ReceiveAuthenticationCode,
         },
    
         // 刷新令牌提供这用来创建和接受令牌
         RefreshTokenProvider = new AuthenticationTokenProvider
         {
             OnCreate = CreateRefreshToken,
             OnReceive = ReceiveRefreshToken,
         }
     });
    }

    上面的代码启用了应用/外部登陆使用Cookie并且可以使用谷歌身份验证,由授权服务器本身管理账户。

    UseCookieAuthentication扩展方法是用来配置授权服务的,配置选项是:

    AuthorizeEndpointPath:客户端应用程序登录授权的请求地址,它必须以前导斜杠开始,例如:“/Authorize”

    TokenEndpointPath:客户端应用程序直接获得访问令牌的请求地址,它也同样是以前导斜杠开始,例如:“/Token”

    ApplicationCanDisplayErrors:如果Web应用程序想要在/Authorize地址为客户端验证生成一个自定义的错误页那么设置为true,浏览器不重定向到客户端应用。例如当client_id或者redirect_uri是错误的,/Authorize可能希望看到“oauth.Error”、“oauth.ErrorDescription”和“oauth.ErrorUri”属性被添加到Owin环境中。

    AllowInsecureHttp:如果设置为true,代表授权和令牌地址允许不安全的Http协议。

    Provider:配置授权服务中间件处理认证和授权的事件。

    AuthorizationCodeProvider:产生一个一次性使用的验证码给客户端应用程序,OnCreate创建授权码,OnReceive收到授权码。

    RefreshTokenProvider:产生一个刷新Token在需要的时候用来获得新的访问Token。

    Oauth不关心在哪儿或怎么去管理你的账号信息,它是有Asp.Net Indentity来负责的,在本教程我们将简化账户管理的代码只确保用户可以使用Owin cookie中间件登录,如下在AccountControl中的简单代码:

    public class AccountController : Controller
    {
        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();
        }
    
        public ActionResult Logout()
        {
            return View();
        }
    
        public ActionResult External()
        {
            var authentication = HttpContext.GetOwinContext().Authentication;
            if (Request.HttpMethod == "POST")
            {
                foreach (var key in Request.Form.AllKeys)
                {
                    if (key.StartsWith("submit.External.") && !string.IsNullOrEmpty(Request.Form.Get(key)))
                    {
                        var authType = key.Substring("submit.External.".Length);
                        authentication.Challenge(authType);
                        return new HttpUnauthorizedResult();
                    }
                }
            }
            var identity = authentication.AuthenticateAsync("External").Result.Identity;
            if (identity != null)
            {
                authentication.SignOut("External");
                authentication.SignIn(
                    new AuthenticationProperties { IsPersistent = true },
                    new ClaimsIdentity(identity.Claims, "Application", identity.NameClaimType, identity.RoleClaimType));
                return Redirect(Request.QueryString["ReturnUrl"]);
            }
    
            return View();
        }
    }
    private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
    {
        if (context.ClientId == Clients.Client1.Id)
        {
            context.Validated(Clients.Client1.RedirectUrl);
        }
        else if (context.ClientId == Clients.Client2.Id)
        {
            context.Validated(Clients.Client2.RedirectUrl);
        }
        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))
        {
            if (clientId == Clients.Client1.Id && clientSecret == Clients.Client1.Secret)
            {
                context.Validated();
            }
            else if (clientId == Clients.Client2.Id && clientSecret == Clients.Client2.Secret)
            {
                context.Validated();
            }
        }
        return Task.FromResult(0);
    }
    private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
    {
        if (context.ClientId == Clients.Client1.Id)
        {
            context.Validated(Clients.Client1.RedirectUrl);
        }
        else if (context.ClientId == Clients.Client2.Id)
        {
            context.Validated(Clients.Client2.RedirectUrl);
        }
        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))
        {
            if (clientId == Clients.Client1.Id && clientSecret == Clients.Client1.Secret)
            {
                context.Validated();
            }
            else if (clientId == Clients.Client2.Id && clientSecret == Clients.Client2.Secret)
            {
                context.Validated();
            }
        }
        return Task.FromResult(0);
    }

     ValidateClientRedirectUri用于验证被注册的跳转Url。ValidateClientAuthentication 验证从Basic架构的请求头或Form表单提交过来的客户端凭证。

  • 相关阅读:
    Helm安装带验证的ElasticSearch 6.x 7.x 集群
    K8S权限控制,限制用户在多个namespace上的访问权限
    Helm安装spinnaker到k8s集群
    离线安装spinnaker到K8S集群
    Kubernetes之CronJob
    GO语言GIN框架入门
    Kubernetes kubectl 命令概述
    Kubernetes Service
    Kubernetes Ingress
    centos+Jenkins+maven搭建持续集成
  • 原文地址:https://www.cnblogs.com/caoshiqing/p/6020378.html
Copyright © 2020-2023  润新知