基於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.cscookie

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擴展方法是用來配置受權服務的,配置選項是:mvc

AuthorizeEndpointPath:客戶端應用程序登陸受權的請求地址,它必須之前導斜槓開始,例如:「/Authorize」app

TokenEndpointPath:客戶端應用程序直接得到訪問令牌的請求地址,它也一樣是之前導斜槓開始,例如:「/Token」asp.net

ApplicationCanDisplayErrors:若是Web應用程序想要在/Authorize地址爲客戶端驗證生成一個自定義的錯誤頁那麼設置爲true,瀏覽器不重定向到客戶端應用。例如當client_id或者redirect_uri是錯誤的,/Authorize可能但願看到「oauth.Error」、「oauth.ErrorDescription」和「oauth.ErrorUri」屬性被添加到Owin環境中。ide

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表單提交過來的客戶端憑證。

相關文章
相關標籤/搜索