zoukankan      html  css  js  c++  java
  • WCF身份验证之用户名密码认证

    WCF支持多种认证技术,例如Windowns认证、X509证书、Issued Tokens、用户名密码认证等,在跨Windows域分布的系统中,用户名密码认证是比较常用的,要实现用户名密码认证,就必须需要X509证书,用来加密用户名和密码。

    1. 创建数字证书  

        makecert -sr localmachine -ss My -n CN=ejiyuan -sky exchange -pe -r。

    2. 创建服务代码 

    [ServiceContract]
        
    public interface ICalculator
        {
            [OperationContract]
            
    double add(double x, double y);
        }

        
    public class CalculatorService : ICalculator
        {

            
    public double add(double x, double y)
            {
                
    return x + y;
            }
        }
        
    class Program
        {
            
    static void Main(string[] args)
            {
                ServiceHost _serviceHost 
    = new ServiceHost(typeof(CalculatorService));
                _serviceHost.Opened 
    += (s, q) =>
                { 
                    Console.WriteLine(
    "服务已启动");
                    Console.Read(); 
                };
                _serviceHost.Open();
            }
        }

    3. 设置安全验证模式 

       <bindings>
          
    <netTcpBinding>
            
    <binding name="nonSessionBinding">
              
    <!--当前绑定的安全认证模式-->
              
    <security mode="Message" >
                
    <!--定义消息级安全性要求的类型,为证书-->
                
    <message clientCredentialType="UserName" />
              
    </security>
            
    </binding>
          
    </netTcpBinding>
        
    </bindings>

      

    4. 设置服务凭据值

        <behaviors>
          
    <serviceBehaviors >
            
    <behavior name="CalculatorServiceBehavior" >
              
    <serviceCredentials>
                
    <!--指定一个 X.509 证书,用户对认证中的用户名密码加密解密-->
                
    <serviceCertificate findValue="CN=ejiyuan" x509FindType="FindBySubjectDistinguishedName" storeLocation="LocalMachine" storeName="My"/>
                
    <clientCertificate>
                  
    <!--自定义对客户端进行证书认证方式 这里为 None-->
                  
    <authentication certificateValidationMode="None"/>
                
    </clientCertificate> 
                
    <!--自定义用户名和密码验证的设置-->            
                
    <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Wcf.Extensions.Security.UserNamePasswordValidator,Wcf.Extensions.Security" />           
              
    </serviceCredentials>          
            
    </behavior>
          
    </serviceBehaviors>
        
    </behaviors>

      

    5. 自定义证书验证
       通过继承自'System.IdentityModel.Selectors.UserNamePasswordValidator',然后我们重写里面的'Validate'方法来实现用户名密码认证逻辑

        public class UserNamePasswordValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
        {
            
    public override void Validate(string userName, string password)
            {
                
    if (userName != "ejiyuan" || password != "123456")
                {
                    
    throw new System.IdentityModel.Tokens.SecurityTokenException("Unknown Username or Password");
                }
            }
        }

    6. 客户端代码   

        class Program
        {
            
    static void Main(string[] args)
            {
                CalculatorClient client 
    = new CalculatorClient();
                
    //指定认证的用户名和密码
                client.ClientCredentials.UserName.UserName = "ejiyuan";
                client.ClientCredentials.UserName.Password 
    = "123456";

                var q 
    = client.add(12);
                Console.WriteLine(client.add(
    1,2));
                Console.Read();
            }
        }

    7. 客户端配置信息(自动生成的)  

        <system.serviceModel>
            
    <bindings>
                
    <netTcpBinding>
                    
    <binding name="NetTcpBinding_ICalculator" >
                        
    <security mode="Message">
                            
    <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                            
    <message clientCredentialType="UserName" />
                        
    </security>
                    
    </binding>
                
    </netTcpBinding>
            
    </bindings>
            
    <client>
                
    <endpoint address="net.tcp://192.168.101.13:8000/calculatorservice"
                    binding
    ="netTcpBinding" bindingConfiguration="NetTcpBinding_ICalculator"
                    contract
    ="ServiceReference1.ICalculator" name="NetTcpBinding_ICalculator">
                    
    <identity>
                        
    <certificate encodedValue="AwAAAAEAAAAUAAAAgvtzbyRkxIGFn4UuyxD2+XJsJl8gAAAAAQAAAPQBAAAwggHwMIIBWaADAgECAhB/oj2gX287pUAmeLEVtWucMA0GCSqGSIb3DQEBBAUAMBIxEDAOBgNVBAMTB2VqaXl1YW4wHhcNMTAwNTI4MDkyNjQzWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdlaml5dWFuMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfOgnw6Vs7gS52Gsud0WsuFOoDeF4+4DL1HFIpQupdExtIkWwY2v2/t/pWHRRvPE/aPf3M6axUYaT4pQqPXBHQR1lb0Hi6XLUGkzsEk7tjiEMEkpt+/8rQIdtXlmmry7yDixoX8PKEd5cGAISjEdbVKJqjQnC55rQXeDYlIXoqlwIDAQABo0cwRTBDBgNVHQEEPDA6gBCTu+dYQbdaauBGEk3SjJ5FoRQwEjEQMA4GA1UEAxMHZWppeXVhboIQf6I9oF9vO6VAJnixFbVrnDANBgkqhkiG9w0BAQQFAAOBgQA1jOywoJ5Xh6B6W3Vw7xPa9A6AH0WtedXPd4YbCU465UdKeP5G2HtKLpS20MnkU6lIh22lxMnb3WGZh70l5Sg1Hl0j/SklLKtOXzeQnVLaPundd9RS1TD/hHwVyu+89cr0866etfGwI9IDpwjhj5ixT3VUHI3eGrXRj+IGx8/W8Q==" />
                    
    </identity>
                
    </endpoint>
            
    </client>
        
    </system.serviceModel>

    备注:基于UserNamePasswordValidator的认证方式,Validator中可以知道相应的UserName和Password,在Service中直接使用OperationContext.Current.ServiceSecurityContext.PrimaryIdentity即可获取当前登录用户信息。

  • 相关阅读:
    BestCoder Round #29 1003 (hdu 5172) GTY's gay friends [线段树 判不同 预处理 好题]
    POJ 1182 食物链 [并查集 带权并查集 开拓思路]
    Codeforces Round #288 (Div. 2) E. Arthur and Brackets [dp 贪心]
    Codeforces Round #287 (Div. 2) E. Breaking Good [Dijkstra 最短路 优先队列]
    Codeforces Round #287 (Div. 2) D. The Maths Lecture [数位dp]
    NOJ1203 最多约数问题 [搜索 数论]
    poj1426
    POJ 1502 MPI Maelstrom [最短路 Dijkstra]
    POJ 2785 4 Values whose Sum is 0 [二分]
    浅析group by,having count()
  • 原文地址:https://www.cnblogs.com/ejiyuan/p/1748429.html
Copyright © 2011-2022 走看看