The previous write the WCF account password authentication, realizes the account password authentication, next looks how to the method fine-grained control, this article very much has referenced the WCF security based on the custom declaration authorization policy, this article has spoken the principle to be clear, but I this article, at most, calculates the operation implementation to carry on the addendum.
Custom permission access requires you to implement two classes
- Custom authorization policy Claim set Manager: Find out all permissions for a user
- Custom Manager for service authorization access checks: The current access resource is compared with the permission set and gives the results of the access
1. Custom authorization policy claim set manager
Note that you need to always allow metadata request (MEX) https://msdn.microsoft.com/en-us/library/aa347849 (v=vs.110). aspx
Using system;using system.linq;using system.servicemodel;using system.servicemodel.description;using System.identitymodel.claims;using system.security.principal;namespace wcf_userpassword{public class Customserviceauthorizationmanager:serviceauthorizationmanager {protected override bool Checkaccesscore (Operat Ioncontext operationcontext) {//Always allow metadata request (MEX) if (Operationcontext.endpointdispatcher. Contractname = = Servicemetadatabehavior.mexcontractname && operationContext.EndpointDispatcher.Contract Namespace = = "Http://schemas.microsoft.com/2006/04/mex" && operationContext.IncomingMessageHeaders.Acti on = = "Http://schemas.xmlsoap.org/ws/2004/09/transfer/Get") {genericidentity identity = new Gen Ericidentity ("");//must be inserted into a principal operationcontext.servicesecuritycontext.authorizationcontext.properties[ "Principal"] = new GenericPrincipal (identity, NULL); return true; }//access method string action = OperationContext.RequestContext.RequestMessage.Headers.Action; String userName = ""; foreach (ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets) { Locate the user name foreach (Claim Claim in CS. Findclaims (Claimtypes.name, Rights.possessproperty)) {userName = claim. Resource.tostring (); } if (CS. Issuer = = Claimset.system)//If this claim is issued by the application. The {///parameter ClaimType should be an open member of Claimtypes, but it doesn't matter, it's a string anyway, as long as the same can be var result = cs. FirstOrDefault (c = c.resource.tostring () = = Action && C.claimtype = = "net.tcp://customclaimset/" && C.right = = Rights.possessproperty); if (result = null) {//must be inserted into a principal genericidentity I Dentity = New GenericIdentity (""); operationcontext.servicesecuritycontext.authorizationcontext.properties["Principal"] = new GenericPrincipal ( identity, NULL); Console.WriteLine ("Consent {0} access, uri:{1}", username,action); return true; }}} Console.WriteLine ("Access Denied, uri:{0}", action); Console.WriteLine (); return false; } }}
2. Custom authorization policy claim set manager
Using system;using system.collections.generic;using system.linq;using system.identitymodel.claims;using System.identitymodel.policy;namespace wcf_userpassword{class Customauthorizationpolicy:iauthorizationpolicy { String id = string. Empty; Public Customauthorizationpolicy () {id = new Guid (). ToString ();//Each claim set is a unique}//evaluates whether the user complies with the claims based on this authorization policy public bool Evaluate (Evaluationcontext Evaluationcon Text, ref object state) {BOOL flag = false; BOOL R_state = false; if (state = = null) {state = R_state;} else {r_state = Convert.toboolean (state);} if (!r_state) {ilist<claim> claims = new list<claim> ();//entity declaration set Forea CH (ClaimSet cs in evaluationcontext.claimsets) {foreach (Claim Claim in CS). Findclaims (Claimtypes.name, Rights.possessproperty)) {var UsernamE = claim. Resource.tostring (); Claims = claims. Concat (Getoperatorclaims (UserName, "net.tcp://customclaimset/", Rights.possessproperty)). ToList (); }} evaluationcontext.addclaimset (this, new Defaultclaimset (Issuer, claims)); R_state = true; Flag = true; } else {flag = true;} return flag; }//gives the user the ability to declare permissions, which can be used in the database private ilist<claim> getoperatorclaims (string userName, string claimtype, str ing right) {ilist<claim> claimlist = new list<claim> (); if (UserName = = "Admin") {//The first parameter claimtype should be the public member of Claimtypes, this program is best used Claimtypes.authorizationd Ecision, but it doesn't matter, anyway is the string, as long as the same can be Claimlist.add (new Claim (ClaimType, "Http://tempuri.org/IService1/GetData", right)); }//else if (userName = = "admin2")//As a test, there is no admin2 access to GetData method//{// Claimlist.add (New Claim (ClaimType, "Http://tempuri.org/IService1/GetData", right)); } return claimlist; } #region Iauthorizationcomponent Member/property implementation public ClaimSet Issuer {//claimset.system represents the application Trusted issuer's System.IdentityModel.Claims.ClaimSet object get {return claimset.system;} The other is claimset.windows a set of claims that contain Windows security identifiers for Windows policy validation, which is not appropriate here} public string Id {ge t {return ID;} } #endregion}}
This code colorful a large, in fact, is also from the Microsoft Forum code (can not find the original address), involving more knowledge, if the claim, principal is not familiar with, suggest to see Jing Jinnan "WCF Technical Analysis" under the seventh chapter, understand the principle behind, More meaningful than implementing the code
3. The following is a WCF configuration operation
Before you do this, compile or run it, because the two classes added above need to be referenced
Increase serviceauthorization in service behavior
Change Principalpermissionmode to Custom
Modified Serviceauthorizationmanagertype to Wcf_userpassword.customserviceauthorizationmanager, WCF_UserPassword
Pop-up dialog box, select Bin–> Debug
Go ahead and you will see the successful compilation of Customserviceauthorizationmanager
Select it, and the WCF Service Configurator becomes this way
Then switch to the authorization policy and add the authorization policy
Like Customserviceauthorizationmanager, choose Customauthorizationpolicy
Operation to here, remember to save
In fact, directly copy the app. config is more convenient, you just need to modify the inside part of the string (below is VS2013, compared to VS2010, to be a lot more refreshing)
<serviceBehaviors>
<behavior name= "Servicebehaviortouserpassword" >
<servicemetadata httpgetenabled= "true"/>
<servicedebug includeexceptiondetailinfaults= "true"/>
<serviceCredentials>
<servicecertificate findvalue= "Myservercert" x509findtype= "Findbysubjectname"/>
<usernameauthentication usernamepasswordvalidationmode= "Custom" customusernamepasswordvalidatortype= "WCF_ Userpassword.mycustomvalidator,wcf_userpassword "/>
</serviceCredentials>
<!--The following sections, copy-
<serviceauthorization principalpermissionmode= "Custom" serviceauthorizationmanagertype= "WCF_ Userpassword.customserviceauthorizationmanager,wcf_userpassword ">
<authorizationPolicies>
<add policytype= "Wcf_userpassword.customauthorizationpolicy, Wcf_userpassword, Version=1.0.0.0, Culture=neutral , Publickeytoken=null "/>
</authorizationPolicies>
</serviceAuthorization>
<!--copy to here--
</behavior>
</serviceBehaviors>
4. Testing
Client
static void Main (string[] args) {var proxy = new Servicereference1.service1client (); Console.WriteLine ("Now is admin access"); Proxy. ClientCredentials.UserName.UserName = "admin"; Proxy. ClientCredentials.UserName.Password = "admin"; try {Console.WriteLine (proxy). GetData (2)); } catch (Exception e) {Console.WriteLine (e.message); } Console.WriteLine (); Proxy = new Servicereference1.service1client (); Console.WriteLine ("Now is admin2 access"); Proxy. ClientCredentials.UserName.UserName = "admin2"; Proxy. ClientCredentials.UserName.Password = "admin2"; try {Console.WriteLine (proxy). GetData (2)); } catch (Exception e) {Console.WriteLine (e.message); } }
Results
Source
Ok
WCF Permissions Control