您现在的位置是:网站首页> 内容页

【干货】基于Owin WebApi 使用OAuth2进行客户端授权服务

  • 公海555000赌船
  • 2019-05-29
  • 17人已阅读
简介前言:采用ClientCredentials方式,即密钥key/password场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似。让用户通过客户端去获取

前言:采用Client Credentials方式,即密钥key/password场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似。

让用户通过客户端去获取自己的token,在根据这个token去获取资源。

本地登录凭据流

    用户输入名称和密码到客户端。客户端将这些凭据发送到授权服务器。授权服务器验证凭据并返回访问令牌。要访问受保护资源,客户端在HTTP请求的Authorization标头中包含访问令牌。

服务实现:

使用WebApi基于Microsoft.Owin.Security.OAuth实现,新建一个空为WebApi项目。

using Microsoft.Owin.Securityusing Microsoft.Owin.Security.OAuthusing Systemusing System.Collections.Genericusing System.Linqusing System.Security.Claimsusing System.Threading.Tasksusing System.Webnamespace ApiThrottleDemo{ public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider { /// <summary> /// 验证客户[client_id与client_secret验证] /// </summary> public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { //http://localhost:48339/token string client_id string client_secret context.TryGetFormCredentials(out client_id out client_secret) if (client_id == "zara" && client_secret == "123456") { context.Validated(client_id) } else { //context.Response.StatusCode = Convert.ToInt32(HttpStatusCode.OK) context.SetError("invalid_client" "client is not valid") } return base.ValidateClientAuthentication(context) } /// <summary> /// 客户端授权[生成access token] /// </summary> public override Task GrantClientCredentials(OAuthGrantClientCredentialsContext context) { var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType) oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name "iphone")) var ticket = new AuthenticationTicket(oAuthIdentity new AuthenticationProperties() { AllowRefresh = true }) context.Validated(ticket) return base.GrantClientCredentials(context) } /// <summary> /// 刷新Token[刷新refresh_token] /// </summary> public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context) { //enforce client binding of refresh token if (context.Ticket == null || context.Ticket.Identity == null || !context.Ticket.Identity.IsAuthenticated) { context.SetError("invalid_grant" "Refresh token is not valid") } return base.GrantRefreshToken(context) } }}

  在此其中呢,需要继承OAuthAuthorizationServerProvider并重写自己想重写的方法,其内部定义下图所示:

 当然这还没完,我们还需要去配置应用程序。在Startup.cs,我们要开启BearerToken认证模式;该Provider属性指定了一个插入OWIN中间件的提供程序,并处理由中间件引发的事件。

以下是应用想要获取令牌时的基本流程:

要获取访问令牌,应用程序会向〜/ Token发送请求。OAuth中间件调用GrantResourceOwnerCredentials提供程序。提供程序调用ApplicationUserManager以验证凭据并创建声明标识。如果成功,则提供程序会创建一个身份验证票证,用于生成令牌。

app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/token") Provider = new ApplicationOAuthProvider() AccessTokenExpireTimeSpan = TimeSpan.FromHours(2) AuthenticationMode = AuthenticationMode.Active AllowInsecureHttp = true })

  其中AccessTokenExpireTimeSpan参数是token过期时间,AllowInsecureHttp 是否开启安全验证,TokenEndpointPath就是你获取token对于服务器的相对路径那我们都知道用户只能访问我们的Api那如何在api上去走Oauth呢?

客户端获取票据

在控制器种创建一个控制器,命名为:OAuth2Controller。

[RoutePrefix("api/v1/oauth2")] public class OAuth2Controller : ApiController { [Authorize] [Route("news")] public async Task<IHttpActionResult> GetNewsAsync() { var authentication = HttpContext.Current.GetOwinContext().Authentication var ticket = authentication.AuthenticateAsync("Bearer").Result var claimsIdentity = User.Identity as ClaimsIdentity var data = claimsIdentity.Claims.Where(c => c.Type == "urn:oauth:scope").ToList() var claims = ((ClaimsIdentity)Thread.CurrentPrincipal.Identity).Claims return Ok(new { IsError = true Msg = string.Empty Data = Thread.CurrentPrincipal.Identity.Name + " It"s about news !!! token expires: " + ticket.Properties.Dictionary.ToString() }) } }

启用授权验证[WebApiConfig]

在ASP.NET Web API中启用Token验证,需要加上[Authorize]标记,并且配置默认启用验证不记名授权方式

config.SuppressDefaultHostAuthentication() config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType))

  

服务端[/token]获取token需要三个参数,我们使用大家熟悉的PostMan去试一试吧,启动项目。

 那我们不难看到,已经成功获取了access_token,至于这个token的值,只要你的client_id不同它就一定是不会相同的(实在不行你可以搞个GUID),那么我们再构建一个ajax去模拟的获取token吧。

 做个简单的页面:

<!DOCTYPE html><html><head> <meta charset="utf-8" /> <title></title> <script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script></head><body> <input type="text" placeholder="client_id"/><br /> <input type="text" placeholder="client_secret"/><br /> <input type="text" placeholder="your_token"/><br /> <button>获取token</button></body><script> $(function () { $("button").click(function () { $.ajax({ url: "http://localhost:58560/token" type: "post" data: "grant_type=client_credentials&client_id=zara&client_secret=123456" success: function (res) { console.log(res) } }) }) })</script></html>  

这是生成的token。

最后总结,你可以在ValidateClientAuthentication中进行身份判断,如果有这个身份,那么我就存储DB中,这样的话,类似于一个微信身份授权的功能基本上就是这样了。

1 0 9)

文章评论

Top