• FluorineFX的验证(Authentication)与授权(Authorization)


    一些基本概念:

    验证(Authentication)指的是确定用户身份的过程,而授权(Authorization)指的是经过上面的过程之后给予用户访问特定资源的权限;说明白一点,验证就是知道"你是谁",而授权则是"让你可以做什么"

    .NET为实现这两个过程提供了Principal和Identity对象。其中,基于角色的安全性基础建立在Principal对象之上,该对象封装了当前用户的信息,既包含用户身份,也包含他所扮演的角色;用户身份用Identity对象来指明,Identity对象中不仅包含指定的用户身份信息(用户名称或账号),还包括了"如何验证这一身份"的方法

    Identity对象是实现了IIdentity接口的类的实例。IIdentity接口包括三个只读属性:

    string AuthenticationType(get;} 获取所使用的身份验证的类型
    bool IsAuthenticated{get;} 登录用户是否经过验证
    string Name {get;} 获取当前用户的名称

    GenericIdentity类

    GenericIdentity类其实相当简单,它并不与任何特定的验证协议相关联。因此,它往往被用在采用了自定义登陆机制的场合。比如一个程序可以自己提示用户输入用户名和密码,然后到自定义的用户数据库中去查询。假如用户名和密码有效,那么程序就会创建一个基于数据库中的匹配记录的principal和(对应的)identity对象。

    GenericIdentity类除了三个IIdentity接口定义的属性之外没有更多的东西了。不过,GenericIdentity类提供了两个构造函数。一个构造函数接受一个字符串参数,该参数指定的是用户名;另一个构造函数接受两个参数:第一个是用户名字符串,第二个是给定的验证类型字符串。
    public GenericIdentity(string name);
    public GenericIdentity(string name, string type);

    Principal对象是实现了IPrincipal接口的类的实例,这些对象用来表示用户,并且包括了用户的身份信息。System.Security.Principal命名空间包括了几种类型的Principal类,这些类中封装了程序代码运行的的安全环境(security context)

    对于每一个线程来说都与一个principal对象相关联。这个principal对象包括了表示运行当前线程的用户的identity对象。我们可以利用Thread类的静态属性CurrentPrincipal来获得这个principal对象。

    下面我们来看看IPrincipal接口,该接口只有一个Identity公共属性和IsInRole公共方法:

    1、Identity属性指向一个与principal 对象关联的IIdentity对象。

    2、IsInRole方法需要一个字符串参数,该字符串是一个角色的名称,并且返回布尔值,指出principal对象是否属于指定的角色。

    GenericPrincipal类

    GenericPrincipal类用来表示一个通过自定义验证的用户,通常与GenericIdentity类一起使用。下面是一段简单的程序,说明了这两个类如何使用:
    //创建一个GenericIdentity对象
    IIdentity myGenericIdentity = new GenericIdentity(strUserName, "MyAuthenticationType");

    //创建一个GenericPrincipal对象
    String[] roles = null;
    GenericPrincipal myGenericPrincipal = new GenericPrincipal(myGenericIdentity, roles);

    //将创建的GenericPrincipal对象附加到当前线程上
    Thread.CurrentPrincipal = myGenericPrincipal;

    注重在上面的例子中,我们可以把MyAuthenticationType的验证类型换成熟知的Kerberos身份验证或者NTLM身份验证。

    //下面是验证的过程:
    //取得当前线程的principal对象
    IPrincipal principal = Thread.CurrentPrincipal;

    if (!principal.Identity.Name.Equals("TrustedUser"))
    {
    throw new SecurityException(
    strUserName + " NOT PERMITTED to proceed.\n");
    }
    Console.WriteLine(
    strUserName + " is PERMITTED to proceed.\n");

    step 1: 自定义一个MyLoginCommand类并继承于FluorineFx.Security.GenericLoginCommand(此类实现了ILoginCommand接口)基类,并重写DoAuthentication方法

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;
    using System.Security.Principal;
    using FluorineFx.Security;
    namespace ServiceLibrary8
    {
        
    public class
     MyLoginCommand : GenericLoginCommand
        {
            
    public
    override IPrincipal DoAuthentication(string username, Hashtable credentials)
            {
                string password = credentials[
    "password"
    ].ToString();
                if (username == 
    "admin"
     && password == 
    "admin"
    )
                {
                    GenericIdentity identity = 
    new
    GenericIdentity(username);
                    GenericPrincipal principal = 
    new
    GenericPrincipal(identity, 
    new
    string[] { 
    "admin"
    , 
    "privilegeduser"
     });
                    
    return
     principal;
                }
                else
                {
                   
    //To get this error message as "faultString" thow a SecurityException with the message
     
                   
    //However the first CommandMessage will mess up the result (faultString>faultDetail), and only for subsequent RemotingMessages will work.
     
                   
    //throw new SecurityException("Not a valid username or password");
     
                    
    return
     null;
                }
            }
        }
    }

    step 2: 定义一个远程服务接口MyLoginService

    using System;
    using System.Collections.Generic;
    using System.Text;
    using FluorineFx;
    namespace ServiceLibrary8
    {
       
    /// <summary>
     
       
    /// MyLoginService is used to force setCredentials sending out credentials
     
       
    /// For Flash this is also used to log out.
     
       
    /// MyLoginService被用来强制使得(Flex的)setCredentials发送验证信息
     
       
    /// 对于flash它也可以用来实现注销登录
     
       
    /// </summary>
     
        [RemotingService]
        
    public class
     MyLoginService
        {
            
    public
    MyLoginService()
            {
            }
            
    public
    bool Login()
            {
                
    returntrue
    ;
            }
            
    public
    bool Logout()
            {
               
    //FormsAuthentication.SignOut();new
    MyLoginCommand().Logout(null);
                
    returntrue
    ;
            }
        }
    }

    step 3: 定义实际业务操作类SecureService(经过验证后才能访问到的类)

    using System;
    using FluorineFx;
    namespace ServiceLibrary8
    {
       
    /// <summary>
     
       
    /// Summary description for SecureService
     
       
    /// </summary>
     
        [RemotingService()]
        
    public class
     SecureService
        {
            
    public
    SecureService()
            {
            }
            
    public
    string GetSecureData()
            {
                
    return"Secure data sent from server."
    ;
            }
        }
    }

    step 4: 配置services-config.xml,确保有以下节点内容:

    <security-constraint id=
    "privileged-users"
    >
     <auth-method>Custom</auth-method>
     <roles>
      <role>admin</role>
      <role>privilegeduser</role>
     </roles>
    </security-constraint>
    <login-command 
    class
    =
    "ServiceLibrary8.MyLoginCommand"
     server=
    "asp.net"
    />

    step 5: 配置remoting-config.xml,确保有以下节点内容:

    <destination id=
    "fluorine"
    >
      <properties>
        <source>*</source>
      </properties>
      <security>
        <security-constraint ref=
    "privileged-users"
    />
      </security>
    </destination>
    <destination id=
    "login"
    >
      <properties>
        <source>ServiceLibrary8.MyLoginService</source>
      </properties>
    </destination>

    step 6: 新建Flex项目,并编写如下代码:

    <?xml version=
    "1.0"
     encoding=
    "utf-8"
    ?>
    <mx:Application xmlns:mx=
    "http://www.adobe.com/2006/mxml"
     layout=
    "absolute"
    >
      <mx:Script>
        <![CDATA[
         
    import
    mx.rpc.events.ResultEvent;
         
    import
    mx.utils.ObjectUtil;
         
    import
    mx.controls.Alert;
         
    import
    mx.rpc.events.FaultEvent;
     
         
    /* Call the login service*/private function
     logIn():
    void
         {  
            
    //use remote object method setCredentials to//enable Flex to send the values required
      loginRO.logout();
              loginRO.setCredentials(username.text, password.text);
          loginRO.Login();
         }
     
         
    /*Call logout*/private function
     logOut():
    void
         {  
      loginRO.logout();
              appViews.selectedChild = loginView;
         }
         
    private function
     getSecureData():
    void
         {  
          fluorineRO.GetSecureData();
         }
    
    /* Display error messages returned */private function
     serverFault(event:FaultEvent):
    void
         {
             Alert.show( ObjectUtil.toString(event.fault.faultString), 
    "Error"
    , mx.controls.Alert.OK );
         }
          
         
    private function
     loginResult(event:ResultEvent):
    void
         {
      
    var
    result:Boolean = event.result  
    as
      Boolean;
              appViews.selectedChild = secureView;
              }
          
         
    private function
     loginFault(event:FaultEvent):
    void
         {
              
    //Alert.show("Authentication failed", "Errors", mx.controls.Alert.OK);
              Alert.show( ObjectUtil.toString(event.fault), 
    "Authentication failed"
     );
         }
          
         
    private function
     getSecureDataResult(event:ResultEvent):
    void
         {
      
    var
    result:String = event.result  
    as
      String;
              Alert.show(result, 
    "Secure data"
    , mx.controls.Alert.OK);
               }
        ]]>
      </mx:Script>
      <mx:ViewStack id=
    "appViews"
     width=
    "100%"
     height=
    "100%"
    >
      <!--login view-->
        <mx:HBox horizontalAlign=
    "center"
     verticalAlign=
    "middle"
     id=
    "loginView"
     width=
    "100%"
     height=
    "100%"
    >
          <mx:Panel title=
    "Login"
     id=
    "loginPanel"
     horizontalScrollPolicy=
    "off"
     verticalScrollPolicy=
    "off"
    >
            <mx:Form id=
    "loginForm"
    >
              <mx:FormItem label=
    "Username:"
    >
                <mx:TextInput id=
    "username"
    />
              </mx:FormItem>
              <mx:FormItem label=
    "Password:"
    >
                <mx:TextInput id=
    "password"
      displayAsPassword=
    "true"
    />
              </mx:FormItem>
            </mx:Form>
            <mx:ControlBar>
              <mx:Spacer width=
    "100%"
     id=
    "spacer1"
    />
              <mx:Button label=
    "Login"
     id=
    "loginButton"
                  enabled=
    "{(username.text.length == 0 || password.text.length == 0) ? false : true}"
                  toolTip=
    "{loginButton.enabled == true ? 'Click to submit' : 'Enter username and password'}"
     
                  click=
    "logIn()"
     />
            </mx:ControlBar>
          </mx:Panel>
        </mx:HBox>
      <!--end loginView-->
      <!--secure area view, made visible after a successful login-->
        <mx:HBox id=
    "secureView"
     width=
    "100%"
     height=
    "100%"
    >
          <mx:ApplicationControlBar dock=
    "true"
     paddingTop=
    "0"
     paddingBottom=
    "0"
     width=
    "100%"
     >
            <mx:Label text=
    "Action:"
     />
            <mx:Spacer width=
    "5"
    />
            <mx:Button label=
    "Get"
     click=
    "getSecureData()"
    />
            <mx:Spacer width=
    "5"
    />
            <mx:Button label=
    "Logout"
     click=
    "logOut()"
    />
          </mx:ApplicationControlBar>
        </mx:HBox>
      <!--end secure area view-->
      </mx:ViewStack>
      <mx:RemoteObject id=
    "loginRO"
     destination=
    "login"
    >
        <mx:method name=
    "Login"
     result=
    "loginResult(event)"
     fault=
    "loginFault(event)"
     />
      </mx:RemoteObject>
      <mx:RemoteObject id=
    "fluorineRO"
     destination=
    "fluorine"
     source=
    "ServiceLibrary8.SecureService"
    >
        <mx:method name=
    "GetSecureData"
     result=
    "getSecureDataResult(event)"
     fault=
    "serverFault(event)"
     />
      </mx:RemoteObject>
     
    </mx:Application>

    运行项目,只有用"admin"账户成功登陆,才能访问到来自SecureService的数据

  • 相关阅读:
    Android 系统日期时间的获取
    Android What is Application
    Android 所有颜色代码
    Android onNewIntent
    Android Activity管理类
    Android 应用启动渐变效果
    算法的的代价及其度量
    算法的设计与分析
    算法的描述
    数据结构与算法(python版)教程
  • 原文地址:https://www.cnblogs.com/CoderWayne/p/1777899.html
Copyright © 2020-2023  润新知