各種語言實現的oauth認證: http://oauth.net/code/
上一篇文章介紹了如何使用基本的http認證來實現asp.net web api的跨平台安全認證。 這里說明一個如何使用oauth實現的認證。oauth大家可能不陌生。那么這里需要注意的是我們使用的是.net平台一個比較好的開源oauth庫。 DOTNETOPENAUTH。
就像上圖所示,我們需要一個ISSSUE Server來給我們一個token,然后再去資源服務器請求資源,也就是Web API Server。
首先在oAuthIssuer服務端我們需要實現一個DotNetOpenAuth的接口:IAuthorizationServer
對接口的實現:
public class OAuth2Issuer : IAuthorizationServer { private readonly IssuerConfiguration _configuration; public OAuth2Issuer(IssuerConfiguration configuration) { if (configuration == null) throw new ArgumentNullException("configuration"); _configuration = configuration; } public RSACryptoServiceProvider AccessTokenSigningKey { get { return (RSACryptoServiceProvider)_configuration.SigningCertificate.PrivateKey; } } public DotNetOpenAuth.Messaging.Bindings.ICryptoKeyStore CryptoKeyStore { get { throw new NotImplementedException(); } } public TimeSpan GetAccessTokenLifetime(DotNetOpenAuth.OAuth2.Messages.IAccessTokenRequest accessTokenRequestMessage) { return _configuration.TokenLifetime; } public IClientDescription GetClient(string clientIdentifier) { const string secretPassword = "test1243"; return new ClientDescription(secretPassword, new Uri("http://localhost/"), ClientType.Confidential); } public RSACryptoServiceProvider GetResourceServerEncryptionKey(DotNetOpenAuth.OAuth2.Messages.IAccessTokenRequest accessTokenRequestMessage) { return (RSACryptoServiceProvider)_configuration.EncryptionCertificate.PublicKey.Key; } public bool IsAuthorizationValid(DotNetOpenAuth.OAuth2.ChannelElements.IAuthorizationDescription authorization) { //claims added to the token authorization.Scope.Add("adminstrator"); authorization.Scope.Add("poweruser"); return true; } public bool IsResourceOwnerCredentialValid(string userName, string password) { return true; } public DotNetOpenAuth.Messaging.Bindings.INonceStore VerificationCodeNonceStore { get { throw new NotImplementedException(); } } }
在 Web API Server端,我們需要使用Http Message Handler來獲取httprequest信息;並進行是否有授權認證。
public class OAuth2Handler : DelegatingHandler { private readonly ResourceServerConfiguration _configuration; public OAuth2Handler(ResourceServerConfiguration configuration) { if (configuration == null) throw new ArgumentNullException("configuration"); _configuration = configuration; } protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { HttpContextBase httpContext; string userName; HashSet<string> scope; if (!request.TryGetHttpContext(out httpContext)) throw new InvalidOperationException("HttpContext must not be null."); var resourceServer = new ResourceServer(new StandardAccessTokenAnalyzer( (RSACryptoServiceProvider)_configuration.IssuerSigningCertificate.PublicKey.Key, (RSACryptoServiceProvider)_configuration.EncryptionVerificationCertificate.PrivateKey)); var error = resourceServer.VerifyAccess(httpContext.Request, out userName, out scope); if (error != null) return Task<HttpResponseMessage>.Factory.StartNew(error.ToHttpResponseMessage); var identity = new ClaimsIdentity(scope.Select(s => new Claim(s, s))); if (!string.IsNullOrEmpty(userName)) identity.Claims.Add(new Claim(ClaimTypes.Name, userName)); httpContext.User = ClaimsPrincipal.CreateFromIdentity(identity); Thread.CurrentPrincipal = httpContext.User; return base.SendAsync(request, cancellationToken); } }
這里的ResourceServerConfiguration 我們是使用加密證書的。
客戶端調用代碼:
調用API獲取數據之前需要從IssueServer獲取Token。
GetAccessToken:
看一下Token信息:
{"access_token":"gAAAAIoUBVBrZ5jAxe5XeTgnJ8mGwwKsCReknueg4gLGlDQ77lR1yPfxt0yNfWLCBT7hxnHjRjuEwDTJ3J1YAnqML4MIgQg8A2cz2bs0EnxvCMfKnayKEesRM-lxLTFbWMpSxe2Xvjm61IbaXjrMkYDRMnV4Do8-7132tiOLIv02WOGlJAEAAIAAAACJ8F3SsE6cTI1XsioW_xOxHeESDzG16y01Gxm3HikYFUC3XIdekpPw0yMB4tavPmUj-kRyC1halbUX7JKf-Dihm6Ou5mexe9lcYTr9or_kH7WcDN5ZCryUK3OaecvwwjQVr5o9XD2ZyZSNDCNhVRFc5ypvP85zZCBW1KJkP3OTCV4AkMN-ROvgI8jxutYdsLLN-YbB7Ot5iypzWWbW0QxiwOzMEqG9nVtPwnIWOUMOvW5KbiELELhgjap60mwHzGrHG4TtA4jrNy8S9zjixO_q-FrgpAuC06CkSH-R4w9yPCLLDc9m3UoAnknFjd4PUbWLxCvlBpEK2sg03ENa0EOKzc2O5fEic9P-BiYt6afMwTgLkJlGBBjmCBpGZMkfLTw","token_type":"bearer","expires_in":"300","scope":"http:\/\/localhost\/ adminstrator poweruser"}
客戶端調用:
代碼:
http://pan.baidu.com/s/1ntkMbCt