现在的位置: 首页 > 综合 > 正文

BlazeDS的安全

2018年02月07日 ⁄ 综合 ⁄ 共 12220字 ⁄ 字号 评论关闭
文章目录

 

后台hibernate,spring

前台flex

 

如何使用Blazeds安全,请看下文

什么是Blazeds安全?

Blazeds安全用来控制对服务器端destination的访问(destination的配置在后台的remoting-config.xml文件中),Flex客户端只有通过服务端验证才能连接到一个destinationBlazeds使用底层J2EE应用服务器安全框架来支持身份验证和授权。

你可以定义自己的逻辑执行身份验证和授权。

 

在后台我们限制对一个destination的访问是通过为destination添加安全约束

例如

 

我们定义一个安全约束

<security-constraint id="basicUsersSC">

          <auth-method>Custom</auth-method>

              <role>manager</role>

              <role>guest</role>

           </roles>

       </security-constraint>

定义一个有安全约束的destination

<destination id="destinationTest">

<security>

<security-constraint ret="basicUsersSC"/>

</security>

       <properties>

           <factory>spring</factory>

           <source>codeTableViewService</source>

       </properties>

</destination>

 

什么是security constraint

 

一个安全约束确保一个用户在访问destination前必须要经过验证。安全约束中可以定义角色,用户可以以这些角色中的一个访问服务。配置一个安全约束可以使用basic或者自定义验证两者方式。两者的区别是服务端响应方式不同,如果用户为经过验证,basic验证会发生401错误,浏览器弹出一个登录框如下图:

 

 

Custom验证方式会发送一个错误到客户端,一般情况下我们使用custom验证,本文的重点是Custom安全约束。

 

关于login command

Blazeds使用一个登录命令来检查证书和记录登录到服务器的用户。Blazeds包括了实现TomcatJBossBEA,WebLogicWebSpherJRUNJ2EE应用服务器的login command。一个登录命令必须实现flex.messaging.security.LoginCommand接口。示例:

<login-command

           class="flex.messaging.security.TomcatLoginCommand" server="Tomcat">

</login-command>

 

关于安全通道和端点

除了验证和授权用户,你也可以使用安全通道和端点实现一个安全的传输协议。例如下面的AMF通道定义了一个非安全的传输连接

<channel-definition id="samples-amf"

class="mx.messaging.channels.AMFChannel">

<endpoint url="http://{server.name}:8400/myapp/messagebroker/amf"

type="flex.messaging.endpoints.AmfEndpoint"/>

</channel-definition>

Blazeds提供在HTTPS连接上传输数据的安全版本的AMFHTTP通道和端点

下面示例定义了一个AMF通道使用安全的传输机制

e

<channel-definition id="my-secure-amf"

class="mx.messaging.channels.SecureAMFChannel">

<endpoint url="https://{server.name}:9100/dev/messagebroker/amfsecure"

class="flex.messaging.endpoints.SecureAMFEndpoint"/>

</channel-definition>

 


建立安全约束

a 定义约束:

<security>

       <login-command

           class="flex.messaging.security.TomcatLoginCommand" server="Tomcat">

       </login-command>

       <security-constraint id="trusted">

           <!—basic安全约束示例:基本身份验证依赖标准J2EE应用服务器的基验证 -->

           <auth-method>Basic</auth-method>

           <roles>

              <role>manager</role>

              <role>guest</role>

           </roles>

       </security-constraint>

<!—Custom安全约束示例:-->

       <security-constraint id="basicUsersSC">

          <auth-method>Custom</auth-method>

          <roles>

              <role>manager</role>

              <role>guest</role>

           </roles>

       </security-constraint>

</security>

 

配置destination

<destination id="SecurePojo1">

...

<security>

<security-constraint ref= “basicUsersSC "/>//此destination引用的是basicUsersSC custom安全约束

</security>

</destination>

 

<destination id="SecurePojo2">

...

<security>

<security-constraint ref="trusted"/>//此destination引用的是trusted basic安全约束

 

</security>

</destination>


如果要配置的destination太多,而这些destination使用的又是同一个安全约束,则可以使用如下默认约束方式

<default-security-constraint ref="sample-users"/>,如果一个destination再次配置了

securitiy-constraint,会覆盖default-security-constraint。

 

对方法提供安全约束

如下方式可以对某一个destination提供的部分方法使用安全约束。

对应的exclude-methods可以对部分方法不使用安全约束

 

<destination id="sampleIncludeMethods">

<properties>

<source>my.company.SampleService</source>

<include-methods>

<method name="fooMethod"/>

<method name="barMethod" security-constraint="admin-users"/>

</include-methods>

</properties>

<security>

<security-constraint ref="sample-users"/>

</security>

</destination>

 

Custom验证

 

使用custom验证传送验证证书到一个destination,你需要指定一个name和password做为参数到ChannelSet.login方法。通过调用ChannelSet.logout()移除证书。如:channelSet.login(“name”,”pwd”);

 

因为多个destination使用相同通道,所以相应的channelSet对象登录到一个destination会记录了用户到其他的使用了相同通道的destination。如果两个组件使用不同的证书到一个相同的ChannelSet 对象,最后一个证书会有效。调用Logout方法记录所有组件退出destination。服务端如何处理Logout,依赖per-client-authentication属性的配置,如果per-client-authentication设置为false,logout方法会使当前session无效,新的FlexSession对象会自动创建或代替。如果per-client-authentication设置为true,logou方法会清除存储在Flexclient对象中的验证信息,不会使FlexClient或FlexSession对象无效。

 

自定义验证示例

<?xml version=”1.0”?>

<!-- security/SecurityConstraintCustom.mxml -->

<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” width=”100%” height=”100%”

    creationComplete=”creationCompleteHandler();”>

    <mx:Script>

        <![CDATA[

            import mx.controls.Alert;

            import mx.messaging.config.ServerConfig;

            import mx.rpc.AsyncToken;

            import mx.rpc.AsyncResponder;

            import mx.rpc.events.FaultEvent;

            import mx.rpc.events.ResultEvent;

            import mx.messaging.ChannelSet;

// Define a ChannelSet object.

            public var cs:ChannelSet;

           

            // Define an AsyncToken object.

            public var token:AsyncToken;

            // Initialize ChannelSet object based on the

            // destination of the RemoteObject component.

            private function creationCompleteHandler():void {

                if (cs == null)

                    cs = ServerConfig.getChannelSet(remoteObject.destination);                   

            }

            // Login and handle authentication success or failure.

            private function ROLogin():void {

                // Make sure that the user is not already logged in.

                if (cs.authenticated == false) {

                    token = cs.login(“sampleuser”, “samplepassword”);

                    // Add result and fault handlers.

                    token.addResponder(new AsyncResponder(LoginResultEvent, LoginFaultEvent));

                }

            }

            // Handle successful login.

            private function LoginResultEvent(event:ResultEvent, token:Object=null):void {

                switch(event.result) {

                    case “success”:

                        authenticatedCB.selected = true;

                    break;

                    default:

                }

            }

           

            // Handle login failure.

            private function LoginFaultEvent(event:FaultEvent, token:Object=null):void {

                switch(event.fault.faultCode) {

                    case “Client.Authentication”:

                        default:

                            authenticatedCB.selected = false;

                            Alert.show(“Login failure: “ + event.fault.faultString);

                }

            }

            // Logout and handle success or failure.

          private function ROLogout():void {

                // Add result and fault handlers.

                token = cs.logout();

                token.addResponder(new AsyncResponder(LogoutResultEvent,LogoutFaultEvent));

            }

            // Handle successful logout.

            private function LogoutResultEvent(event:ResultEvent, token:Object=null):void {

                switch (event.result) {

                    case “success”:

                        authenticatedCB.selected = false;

                        break;

                    default:

                }

            }

            // Handle logout failure.

            private function LogoutFaultEvent(event:FaultEvent, token:Object=null):void {

                Alert.show(“Logout failure: “ + event.fault.faultString);

            }

            // Handle message recevied by RemoteObject component.

            private function resultHandler(event:ResultEvent):void {

                ta.text += “Server responded: “+ event.result + “/n”;

            }

            // Handle fault from RemoteObject component.

            private function faultHandler(event:FaultEvent):void {

                ta.text += “Received fault: “ + event.fault + “/n”;

            }

        ]]>

    </mx:Script>

    <mx:HBox>

        <mx:Label text=”Enter a text for the server to echo”/>

        <mx:TextInput id=”ti” text=”Hello World!”/>

        <mx:Button label=”Login”

            click=”ROLogin();”/>

        <mx:Button label=”Echo”

            enabled=”{authenticatedCB.selected}”

            click=”remoteObject.echo(ti.text);”/>

        <mx:Button label=”Logout”

            click=”ROLogout();”/>

        <mx:CheckBox id=”authenticatedCB”

            label=”Authenticated?”

            enabled=”false”/>

    </mx:HBox>

<mx:TextArea id=”ta” width=”100%” height=”100%”/>

<mx:RemoteObject id=”remoteObject”

        destination=”remoting_AMF_SecurityConstraint_Custom”

        result=”resultHandler(event);”

        fault=”faultHandler(event);”/>

</mx:Application>

 

 


TOMCAT服务器配置自定义验证

<!--配置这些东西的主要目的就是让Flex端配置的各种验证能够和tomcat的验证联系起来,前面提到的custom验证,用到了channelset.login(name,password)方法,想想通道将密码和用户名提交到了哪里进行了验证呢,下面的配置就有用了。-->

 

A.将flex-tomcat-common.jarflex-tomcat-server.jar放置到TOMCAT/lib.blzaeds目录下面

编辑tomcat/conf/catalina.properties文件,添加如下路径到common.loader 属性${catalina.home}/lib/blazeds/*.jar

 

B.编辑tomcat/conf/context.xml文件,添加如下标签到Context descriptors

<Valve className="flex.messaging.security.TomcatValve"/>

 

C .重启Tomcat

 

 

 

配置Tomcat Realm

(这里的配置完全可以参考tomcat官方的文档http://www.aspzz.com.cn/c/man/Tomcat/realm-howto.html

 

由于Blazeds的安全验证是基于J2EE服务器的安全验证,所以登录的用户(有manager角色)同样能登录到Tomcat服务器。

为了方便管理Blazeds应用程序安全约束中的的用户和角色,我们需要配置Tomcat Realm

默认情况下,登录到Tomcat的用户和角色是存放在tomcat/conf/tomcat-users.xml,如下示例:

<?xml version='1.0' encoding='utf-8'?>

<tomcat-users>

<role rolename="manager"/>

<role rolename="tomcat"/>

<role rolename="admin"/>

<role rolename="guest"/>

<user username="tzl" password="tzl" fullName="Tangzhilong" roles="admin,tomcat,guest"/>

<user username="csn" password="csn" fullName="Chenshangneng"/>

</tomcat-users>

 

什么是Realm

一个Realm就是一个存有用户和密码及用户相关联角色的数据库,用来验证一个web应用的有效用户。Tomcat6定义了一个JAVA接口org.apache.catalina.Realm,,实现了此接口的插件组件能建立和数据库连接,如:JDBCRealm,DataSourceRealm,JNDIRealm等,其中JDBCRealm能通过一个JDBC驱动获取存储在关系数据库的验证信息。下面介绍JDBCRealm的配置。

 

如何配置一个JDBCRealm

A .在你的数据库中必须要有如下格式的两张表。用户表和关联的角色表,示例如下

用户表:

create table users (
  user_name           varchar(15) not null primary key,--登录的用户名
  user_pass           varchar(15) not null---用户的密码
);
用户角色表:
create table user_roles (
  user_name           varchar(15) not null,--用户名
  role_name           varchar(15) not null,--用户角色名
  primary key (user_name, role_name)
);

 

一般情况,你需要一个XML元素到tomcat/conf/server.xml配置文件。对应ORACLE

B.将对应数据库的JDBC驱动放到TOMCAT/LIB目录下面,只有jar文件才能被认到。

C.在tomcat/conf/server.xml中建立一个Realm

D.重启Tomcat服务器

 

关于Realm配置的一些属性

Attribute

Description

className

The fully qualified Java class name of this Realm implementation. You MUST specify the value "org.apache.catalina.realm.JDBCRealm" here.

connectionName

The database username used to establish a JDBC connection.

connectionPassword

The database password used to establish a JDBC connection.

connectionURL

The database URL used to establish a JDBC connection.

digest

The digest algorithm used to store passwords in non-plaintext formats. Valid values are those accepted for the algorithm name by the java.security.MessageDigest class. See Digested Passwords for more information. If not specified, passwords are stored in clear text.

driverName

The fully qualified Java class name of the JDBC driver to be used. Consult the documentation for your JDBC driver for the appropriate value.

roleNameCol

The name of the column, in the user roles table, that contains the name of a role assigned to this user.

userCredCol

The name of the column, in the users table, that contains the password for this user (either in clear text, or digested if the digest attribute is set).

userNameCol

The name of the column, in the users and user roles tables, that contains the username of this user.

userRoleTable

The name of the table that contains one row for each role assigned to a particular username. This table must include at least the columns named by the userNameCol and roleNameCol attributes.

userTable

The name of the table that contains one row for each username to be recognized by Tomcat. This table must include at least the columns named by the userNameCol and userCredCol attributes.

示例:1.我连接的数据库是ORACLE,配置如下:

<Realm className="org.apache.catalina.realm.JDBCRealm"

      driverName="oracle.jdbc.OracleDriver"

      connectionURL="jdbc:oracle:thin:@kerberos:1521:DDD"

       connectionName = "cam" connectionPassword="cam"

      userTable="operator" userNameCol="operatorId" userCredCol="password" userRoleTable="operatorAndRole" roleNameCol="roleName"/>

对应的用户表—operator

operatorid       number(19)                 

code       varchar2(255 char)              

name       varchar2(36 char)               

password       varchar2(255 char)              

employeeid     number(19)   

 

对应的用户角色表—OperatorAndRole

             

operatorroleid number(19)                 

operatorid       number(19)                 

password       varchar2(255 char)              

organizationid number(19)                 

roleid      number(19)                 

rolename varchar2(36 char)               

 

2.Mysql数据库配置:

<Realm className="org.apache.catalina.realm.JDBCRealm"

      driverName="org.gjt.mm.mysql.Driver"

      connectionURL="jdbc:mysql://localhost/ssf?user=root&amp;password=tzl"

      userTable="users" userNameCol="userId" userCredCol="userPwd" userRoleTable="user_role" roleNameCol="role_name"/>

 

 

 

 

抱歉!评论已关闭.