看到园子里面有人写的OAuth,就想把自己实现的OAuth也分享一下,关于OAuth协议这里就不再赘述。

一、作为认证服务器,首先需要提供一个可以通过appid/appsecret来获取token这样的一个接口,于是便有了以下代码。

    public class AuthController : ApiController
{
[HttpGet]
public HttpResponseMessage Token(string appid = "", string appsecret = "")
{
ApiResponseEntity rep;
var isv = AppManage.Instance.GetAppISV(appid, appsecret);
if (isv != null)
{
string token = TokenManage.Instance.CreateToken(appid); rep = new ApiResponseEntity
{
Status = InterfaceStatus.Success,
BizData = new
{
AccessToken = token
}
};
}
else
{
rep = new ApiResponseEntity()
{
Status = InterfaceStatus.Parm_Missing,
Message = "param error"
};
}
return rep.ToHttpResponseMessage();
}
}

创建token的算法可以自行实现,我是将新生成的Guid做了一下md5处理,代码如下:

public string CreateToken(string appid)
{
string token = Guid.NewGuid().ToString().ToMd5();
Set(token, appid);
return token;
}

上文可以看到,在生成token了以后,就一个SetToken,就是将token存储在缓存里面,并设置了一定时间的生存周期,代码如下:

public void Set(string token, string appid)
{
var config = ServerConfigManage.Instance.GetServerConfig();
string key = string.Format(RedisCacheKey.App_Token, token);
RedisNetHelper.Set<string>(key, appid, DateTime.Now.AddSeconds(config.TokenSurvivalTime));
}

为什么要用token做key,是因为token的变更会导致isv token验证失效,但是用token做key就可以在存活周期内,这个key都可以使用,避免了多线程获取token,或是其他原因导致的token失效。作为认证服务器,还需要提供一个RefreshToken这样的接口,用来给刷新token的存活周期,代码相似这里就不再赘述。

二、在Api做验证的时候,就需要开始对Token进行验证了,代码如下:

 public class OAuthHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
ApiResponseEntity repEntity = null;
string appid = "";
string ip = RequestHelper.GetWebClientIp();
if (!OAuthValidate.IpValidate(ip))
{
repEntity = new ApiResponseEntity
{
Status = InterfaceStatus.IllegalIp,
Message = "ip access limit"
};
}
else
{
string token = "";
string url = request.RequestUri.AbsoluteUri;
var routeData = request.GetRouteData();
string controller = routeData.Values["controller"].ToString().ToLower();
string action = routeData.Values["action"].ToString().ToLower();
if (controller.Equals("auth") && action.Equals("token"))
{
return base.SendAsync(request, cancellationToken);
} if (request.Method == HttpMethod.Get)
{
var query = request.RequestUri.ParseQueryString();
token = query["token"];
} if (token == null || token.Length == )
{
repEntity = new ApiResponseEntity
{
Status = InterfaceStatus.Token_Faild,
Message = "token invalid"
};
}
else
{
appid = TokenManage.Instance.Get(token);
if (appid == null || appid.Length == )
{
repEntity = new ApiResponseEntity
{
Status = InterfaceStatus.Token_Faild,
Message = "token invalid"
};
}
else
{
if (!OAuthValidate.ApiValidate
(
string.Format("{0}/{1}", controller, action),
appid
))
{
repEntity = new ApiResponseEntity
{
Status = InterfaceStatus.No_Access,
Message = "api access limit"
};
}
}
}
} if (repEntity != null)
{
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(repEntity.ToHttpResponseMessage());
return tsc.Task;
}
else
{
return base.SendAsync(request, cancellationToken);
}
}
}

使用比较传统的方式,继承于DelegatingHandler,然后进行处理,首先是做的IP验证,然后再进行token有效期验证,最后再进行Api的权限调用验证。验证的代码如下:

 public static bool IpValidate(string ip)
{
var config = ServerConfigManage.Instance.GetServerConfig();
bool isPass = true;
if (isPass && config.IsStartIpWhiteList)
{
isPass = config.IpWhiteList.Contains(ip);
}
if (isPass && config.IsStartIpBlackList)
{
isPass = !config.IpBlackList.Contains(ip);
}
return isPass;
} public static bool ApiValidate(string api, string appid)
{
var config = ServerConfigManage.Instance.GetServerConfig();
if (config.IsStartApiControl)
{
var apis = AppManage.Instance.GetAppApiResource(appid);
return apis != null && apis.Contains(api);
}
return true;
}

GetServerConfig()是从DB/Cache里面获取服务器的自定义配置,然后看是否开启ip白名单/黑名单,下面的代码同理,是否开启权限验证。

那认证服务器到这里实际上就结束了,关于isv申请appid/appsecret。然后用户同意授权以后,存储appid和user之间的关联关系,就需要看客自行实现了。

另外有一个扩展代码这里也提一下,就是关于ApiResponseEntity的返回值处理,代码如下:

public static HttpResponseMessage ToHttpResponseMessage(this ResponseEntity rep, bool isEncrypt = false)
{
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent
(
isEncrypt
? EncryptHelper.Base64Replace(EncryptHelper.AESEncryptBase64(JsonHelper.ToJson(rep), Config.ApiEncryptKey))
: JsonHelper.ToJson(rep),
System.Text.Encoding.UTF8,
"application/json"
)
};
}

自己开发实现OAuth做webapi认证的更多相关文章

  1. OAuth做webapi认证

    OAuth做webapi认证 看到园子里面有人写的OAuth,就想把自己实现的OAuth也分享一下,关于OAuth协议这里就不再赘述. 一.作为认证服务器,首先需要提供一个可以通过appid/apps ...

  2. Nodejs之MEAN栈开发(八)---- 用户认证与会话管理详解

    用户认证与会话管理基本上是每个网站必备的一个功能.在Asp.net下做的比较多,大体的思路都是先根据用户提供的用户名和密码到数据库找到用户信息,然后校验,校验成功之后记住用户的姓名和相关信息,这个信息 ...

  3. 使用OAuth打造webapi认证服务供自己的客户端使用

    一.什么是OAuth OAuth是一个关于授权(Authorization)的开放网络标准,目前的版本是2.0版.注意是Authorization(授权),而不是Authentication(认证). ...

  4. OAuth在WebApi中的使用,前后台分离的调用方式

    前段时间由于公司架构服务层向WebApi转换,就研究了OAuth在WebApi中的使用,这中间遇到了很多坑,在此记录一下OAuth的正确使用方式. 1.  OAuth是做什么的? 在网上浏览时,大家都 ...

  5. OAuth在WebApi

    OAuth在WebApi中的使用,前后台分离的调用方式 前段时间由于公司架构服务层向WebApi转换,就研究了OAuth在WebApi中的使用,这中间遇到了很多坑,在此记录一下OAuth的正确使用方式 ...

  6. OAuth打造webapi认证服务

    使用OAuth打造webapi认证服务供自己的客户端使用 一.什么是OAuth OAuth是一个关于授权(Authorization)的开放网络标准,目前的版本是2.0版.注意是Authorizati ...

  7. 使用OAuth打造webapi认证服务供自己的客户端使用(二)

    在上一篇”使用OAuth打造webapi认证服务供自己的客户端使用“的文章中我们实现了一个采用了OAuth流程3-密码模式(resource owner password credentials)的W ...

  8. ASP.NET Core 认证与授权[3]:OAuth & OpenID Connect认证

    在上一章中,我们了解到,Cookie认证是一种本地认证方式,通常认证与授权都在同一个服务中,也可以使用Cookie共享的方式分开部署,但局限性较大,而如今随着微服务的流行,更加偏向于将以前的单体应用拆 ...

  9. Taurus.MVC WebAPI 入门开发教程8:WebAPI文档与自动化测试。

    系列目录 1.Taurus.MVC WebAPI  入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...

随机推荐

  1. 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino

    大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...

  2. JavaScript中Math对象的方法介绍

    1.比较最值方法 比较最值有两种方法,max() 和 min() 方法. 1.1 max() 方法,比较一组数值中的最大值,返回最大值. var maxnum = Math.max(12,6,43,5 ...

  3. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  4. javascript之活灵活现的Array

    前言 就如同标题一样,这篇文章将会灵活的运行Array对象的一些方法来实现看上去较复杂的应用. 大家都知道Array实例有这四个方法:push.pop.shift.unshift.大家也都知道 pus ...

  5. 多线程爬坑之路-Thread和Runable源码解析

    多线程:(百度百科借一波定义) 多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提 ...

  6. 简约之美Jodd-http--深入源码理解http协议

    Jodd 是一个开源的 Java 工具集, 包含一些实用的工具类和小型框架.简单,却很强大! jodd-http是一个轻巧的HTTP客户端.现在我们以一个简单的示例从源码层看看是如何实现的? Http ...

  7. html5 与视频

    1.视频支持格式. 有3种视频格式被浏览器广泛支持:.ogg,.mp4,.webm. Theora+Vorbis=.ogg  (Theora:视频编码器,Vorbis:音频编码器) H.264+$$$ ...

  8. CSS 3学习——边框

    在CSS 3中可以设置边框圆角.边框阴影和边框图像,分别通过border-radius.border-image和box-shadow属性设置. 边框圆角 border-radius属性是以下4个属性 ...

  9. Spark读写Hbase的二种方式对比

    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 一.传统方式 这种方式就是常用的TableInputFormat和TableOutputForm ...

  10. Node.js学习笔记——Node.js开发Web后台服务

    一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...