自己开发实现OAuth做webapi认证

王朝学院·作者佚名  2016-08-28
窄屏简体版  字體: 小  |  中  |  大  |  超大  

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

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

[flash=500,400]http://s1.knowsky.com/20160211/iydsmu42g5f25.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/bu02omwoose25.gif[/flash]publicclassAuthController : ApiController

{

[HttpGet]publicHttPResponseMessage Token(stringappid ="",stringappsecret ="")

{

ApiResponseEntity rep;varisv =AppManage.Instance.GetAppISV(appid, appsecret);if(isv !=null)

{stringtoken =TokenManage.Instance.CreateToken(appid);

rep=newApiResponseEntity

{

Status=InterfaceStatus.Success,

BizData=new{accessToken=token

}

};

}else{

rep=newApiResponseEntity()

{

Status=InterfaceStatus.Parm_Missing,

Message="param error"};

}returnrep.ToHttpResponseMessage();

}

}

View Code

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

[flash=500,400]http://s1.knowsky.com/20160211/iydsmu42g5f25.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/bu02omwoose25.gif[/flash]publicstringCreateToken(stringappid)

{stringtoken =Guid.NewGuid().ToString().ToMd5();

Set(token, appid);returntoken;

}

View Code

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

[flash=500,400]http://s1.knowsky.com/20160211/iydsmu42g5f25.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/bu02omwoose25.gif[/flash]publicvoidSet(stringtoken,stringappid)

{varconfig =ServerConfigManage.Instance.GetServerConfig();stringkey =string.Format(RedisCacheKey.App_Token, token);

RedisNetHelper.Set<string>(key, appid, DateTime.Now.AddSeconds(config.TokenSurvivalTime));

}

View Code

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

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

[flash=500,400]http://s1.knowsky.com/20160211/iydsmu42g5f25.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/bu02omwoose25.gif[/flash]publicclassOAuthHandler : DelegatingHandler

{protectedoverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)

{

ApiResponseEntity repEntity=null;stringappid ="";stringip=RequestHelper.GetWebClientIp();if(!OAuthValidate.IpValidate(ip))

{

repEntity=newApiResponseEntity

{

Status=InterfaceStatus.IllegalIp,

Message="ip access limit"};

}else{stringtoken ="";stringurl =request.RequestUri.AbsoluteUri;varrouteData =request.GetRouteData();stringcontroller = routeData.Values["controller"].ToString().ToLower();stringaction = routeData.Values["action"].ToString().ToLower();if(controller.Equals("auth") && action.Equals("token"))

{returnbase.SendAsync(request, cancellationToken);

}if(request.Method ==HttpMethod.Get)

{varquery =request.RequestUri.ParseQueryString();

token= query["token"];

}if(token ==null|| token.Length ==0)

{

repEntity=newApiResponseEntity

{

Status=InterfaceStatus.Token_Faild,

Message="token invalid"};

}else{

appid=TokenManage.Instance.Get(token);if(appid ==null|| appid.Length ==0)

{

repEntity=newApiResponseEntity

{

Status=InterfaceStatus.Token_Faild,

Message="token invalid"};

}else{if(!OAuthValidate.ApiValidate

(string.Format("{0}/{1}", controller, action),

appid

))

{

repEntity=newApiResponseEntity

{

Status=InterfaceStatus.No_Access,

Message="api access limit"};

}

}

}

}if(repEntity !=null)

{vartsc =newTaskCompletionSource<HttpResponseMessage>();

tsc.SetResult(repEntity.ToHttpResponseMessage());returntsc.Task;

}else{returnbase.SendAsync(request, cancellationToken);

}

}

}

View Code

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

[flash=500,400]http://s1.knowsky.com/20160211/iydsmu42g5f25.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/bu02omwoose25.gif[/flash]publicstaticboolIpValidate(stringip)

{varconfig =ServerConfigManage.Instance.GetServerConfig();boolisPass =true;if(isPass &&config.IsStartIpWhiteList)

{

isPass=config.IpWhiteList.Contains(ip);

}if(isPass &&config.IsStartIpBlackList)

{

isPass= !config.IpBlackList.Contains(ip);

}returnisPass;

}publicstaticboolApiValidate(stringapi,stringappid)

{varconfig =ServerConfigManage.Instance.GetServerConfig();if(config.IsStartApiControl)

{varapis =AppManage.Instance.GetAppApiResource(appid);returnapis !=null&&apis.Contains(api);

}returntrue;

}

View Code

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

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

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

[flash=500,400]http://s1.knowsky.com/20160211/iydsmu42g5f25.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/bu02omwoose25.gif[/flash]publicstaticHttpResponseMessage ToHttpResponseMessage(thisResponseEntity rep,boolisEncrypt =false)

{returnnewHttpResponseMessage(HttpStatusCode.OK)

{

Content=newStringContent

(

isEncrypt?EncryptHelper.Base64Replace(EncryptHelper.AESEncryptBase64(JsonHelper.ToJson(rep), Config.ApiEncryptKey))

: JsonHelper.ToJson(rep),

System.Text.Encoding.UTF8,"application/json")

};

}

View Code

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航