[.Net] OWIN OAUTH 实现数据持久化和分布式部署

本文使用WebAPI+Owin.OAuth 实现 OAuth认证服务以及资源获取认证

主要讲述如何对令牌(Token)进行持久化存储,以及分布式认证

如果您也感兴趣,可先参考上边两篇文章进行搭建 您的OAuth程序

背景:

使用 WebAPI+Owin.OAuth 非常便捷的搭建起了OAuth认证以及Api接口管控之后,发现了一些不符合使用场景的问题由于公司数据量大,需要认证的API交多,其中有一些比较重要的API,如登陆的API接口,如果认证服务出现异常,将会导致多系统无法正常访问。所以我们需要关注认证服务的稳定性,正常情况下我们会进行分布式架设认证服务,通过负载均衡实现多服务器备源,保证系统稳定使用。

Owin.OAuth认证流程十分便捷:Client端申请AccessToken时,Owin.OAuth会自动认证,并生成返回Token,这个过程会把Token存储在服务端程式中,当Client调用API时,Owin.OAuth又会帮助你验证服务端存储的Token;开发者几乎不用编写任何代码就实现了OAuth认证,但这至少会带来两个问题:

  1. 资源接口必须和认证服务在同一个项目中
  2. 无法多服务器分布部署,因为你不能保证Client每次请求都发生在同一台服务上

所以我们需要获取并存储Token,然后使用我们存储的Token对Client的请求进行验证

实现:
其他关于认证服务和资源接口的搭建大家可以参考上边两篇文章,这边主要讲上述文章没有的内容

1.如何获取TOKEN
Owin.OAuth会自动生成Token并返回给客户端,这个过程未对服务端开放,但我们可以通过重写OAuthAuthorizationServerProvider中的TokenEndpointResponse方法来实现Token的获取

代码如下(ps:如果你不知这段代码应该加载哪里,我建议你先阅读一下 参考资料的两篇文章)

public override async Task TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
        {
            //成功获取到Token
            var token = context.AccessToken;
            //获取到Token的生存时间
            var expiresUtc = context.Properties.ExpiresUtc;
 
            //存储到数据库 
            //dal.Insert(token,expiresUtc)
 
            //调用基类方法
            await base.TokenEndpointResponse(context);
        }

这样我们就可以成功的把 Token获取并存入数据库了,用于多服务器认证

2.如何自定义验证Token
单服务器验证权限时十分简单,我们只需要在API上加上[Authorize]就可以了如下:

[Authorize]
[HttpGet]
public HttpResponseMessage Get()
{
    return new HttpResponseMessage { Content = new StringContent("Hello World!", Encoding.GetEncoding("UTF-8"), "text/plain") };
}
       但该标签只能验证本地的 Token 无法验证我们存储在数据库中的Token,这时,同理我们需要重写一下AuthorizeAttribute类了

代码如下

public class TokenAuthorizeAttribute : AuthorizeAttribute
    {
        DAL.OAuthDAL dal = new DAL.OAuthDAL();
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            base.OnAuthorization(actionContext);
        }
 
        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            //这里你可以填写自己的异常描述
            base.HandleUnauthorizedRequest(actionContext);
        }
 
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            //需要先验证一下Headers中是否有 Authorization 参数
            if (actionContext.Request.Headers.Authorization == null)
            {
                return false;
            }
            bool isok = false;
 
            //通过数据库验证Token是否有效
            //isok=dal.Check(actionContext.Request.Headers.Authorization.Parameter)
 
            //返回验证结果
            return isok;
        }
    }

这时候我们有了一个新的类 TokenAuthorizeAttribute,我们使用它来帮我们验证接口

[TokenAuthorize]
[HttpGet]
public HttpResponseMessage Get()
{
   return new HttpResponseMessage { Content = new StringContent("Hello World!", Encoding.GetEncoding("UTF-8"), "text/plain") };
}

这样我们就可以对认证服务进行多服务器架设部署,以及认证服务与资源接口分离了

结尾:
这些只是我在开发过程中遇见的问题和解决方案,不一定是最好的方法。
大家有什么好的方法也可以指教一下我。

然后:

说到最后,在我做OAuth这几天,我的理解是:OAuth只是提供了一种安全,开放的授权流程,它只关注两点:1.如何生成获取令牌;2.如何验证令牌!它本身并未实现任何代码!如果您的需求比较简单,您可以直接引用Nuget上的包进行快速开发,如果您的需求比较复杂,您也可以直接实现生成令牌和验证令牌

参考资料:

  1. [ASP.NET] 结合Web API在OWIN下实现OAuth
  2. 在ASP.NET中基于Owin OAuth使用Client Credentials Grant授权发放Token

其他认证服务分布式部署参考:

  1. WSO2 Identity Server集群方案
  2. IdentityServer4 集群,只支持.netcore
  3. 认证服务(Oauth、分布式集群session共享问题、单点登录)

转载自:[C#] OWIN OAUTH 实现数据持久化和分布式部署

你可能感兴趣的:(Web,Backend)