本文使用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认证,但这至少会带来两个问题:
所以我们需要获取并存储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上的包进行快速开发,如果您的需求比较复杂,您也可以直接实现生成令牌和验证令牌
参考资料:
其他认证服务分布式部署参考:
转载自:[C#] OWIN OAUTH 实现数据持久化和分布式部署