在基于角色的安全中,有两个重要的概念及其对应的接口:标识与主体. .Net使用标识来表达用户,其接口定义如下:
publicinterface IIdentity { string AuthenticationType { get; } bool IsAuthenticated { get; } string Name { get; } }
最重要的就是用户名Name和是否通过验证IsAuthenticated. .Net使用主体来表达安全上下文
publicinterface IPrincipal { IIdentity Identity { get; } bool IsInRole(string role); } 其包括当前环境的用户与判断用户是否属于某接口.
在不用的应用程序执行上下文中都可以通过获取主体接口来判断当前用户授权与验证信息.在Windowns程序中,通过 System.Threading.Thread.CurrentPrincipal 获取,在Asp.Net中,通过
System.Web.HttpContext.Current.User 获取.
DotNetOpenAuth在资源服务端的作用就是确定请求身份.其编程的核心对象为ResourceServer,通过GetPrincipal方法便可获取请求的主体.
publicclass ResourceServer { public IAccessTokenAnalyzer AccessTokenAnalyzer { get; privateset; } public ResourceServer(IAccessTokenAnalyzer accessTokenAnalyzer) { this.AccessTokenAnalyzer = accessTokenAnalyzer; } publicvirtual IPrincipal GetPrincipal(HttpRequestBase httpRequestInfo = null, paramsstring[] requiredScopes) { AccessToken accessToken = this.GetAccessToken(httpRequestInfo, requiredScopes); string principalUserName = !string.IsNullOrEmpty(accessToken.User) ? this.ResourceOwnerPrincipalPrefix + accessToken.User : this.ClientPrincipalPrefix + accessToken.ClientIdentifier; string[] principalScope = accessToken.Scope != null ? accessToken.Scope.ToArray() : newstring[0]; var principal = new OAuthPrincipal(principalUserName, principalScope); return principal; } publicvirtual AccessToken GetAccessToken(HttpRequestBase httpRequestInfo = null, paramsstring[] requiredScopes) { accessToken = this.AccessTokenAnalyzer.DeserializeAccessToken(request, request.AccessToken); } } 可以看到,程序通过IAccessTokenAnalyzer接口获取访问令牌,实际的实现类为StandardAccessTokenAnalyzer
publicclass StandardAccessTokenAnalyzer : IAccessTokenAnalyzer { public StandardAccessTokenAnalyzer(RSACryptoServiceProvider authorizationServerPublicSigningKey, RSACryptoServiceProvider resourceServerPrivateEncryptionKey) { this.AuthorizationServerPublicSigningKey = authorizationServerPublicSigningKey; this.ResourceServerPrivateEncryptionKey = resourceServerPrivateEncryptionKey; } public RSACryptoServiceProvider AuthorizationServerPublicSigningKey { get; privateset; } public RSACryptoServiceProvider ResourceServerPrivateEncryptionKey { get; privateset; } publicvirtual AccessToken DeserializeAccessToken(IDirectedProtocolMessage message, string accessToken) { var accessTokenFormatter = AccessToken.
CreateFormatter(this.AuthorizationServerPublicSigningKey, this.ResourceServerPrivateEncryptionKey); accessTokenFormatter.Deserialize(token, accessToken, message, Protocol.access_token); return token; } }
很简单,就是通过上文所说的将请求中特定信息反序列化为访问令牌. 实际编程中只需使用上面两个类就可以获取应用程序所需的主体
privatestatic IPrincipal VerifyOAuth2(HttpRequestMessageProperty httpDetails, Uri requestUri, paramsstring[] requiredScopes) { // for this sample where the auth server and resource server are the same site, // we use the same public/private key.using (RSACryptoServiceProvider authorizationRas = GetAuthorizationServerRsa()) { using (RSACryptoServiceProvider resourceRas = GetResourceServerRsa()) { var resourceServer = new ResourceServer(new StandardAccessTokenAnalyzer(authorizationRas, resourceRas)); return resourceServer.GetPrincipal(httpDetails, requestUri, requiredScopes); } } } 上面这段程序截取自Sample,方法参数与编程环境有关.这个是为Wcf获取验证主体.
此主体是DotNetOpenAuth框架对IPrincipal的实现实:OAuthPrincipal,从上面的GetPrincipal方法可以看出,主体的用户名是访问令牌用户名,角色集合为权限范围
publicclass OAuthPrincipal : IPrincipal { private ICollection
ing AccessToken { get; protectedset; } public ReadOnlyCollection
publicclass OAuthIdentity : IIdentity { internal OAuthIdentity(string username) { Requires.NotNullOrEmpty(username, \); this.Name = username; } publicstring AuthenticationType { get { return\; } } publicbool IsAuthenticated { get { returntrue; } } publicstring Name { get; privateset; } }
很简单,就不多说了.
六.小结
就我个人而言,虽然此框架功能强大,但感觉写的过于复杂,有很多处理细节与意图都掩埋于代码之后,有时会出现一些莫明奇妙的处理.希望之后的版本能有所改善.
相关推荐: