BlazeDS的安全
? 后台hibernate,spring 前台flex ? 如何使用Blazeds安全,请看下文 什么是Blazeds安全? Blazeds安全用来控制对服务器端destination的访问(destination的配置在后台的remoting-config.xml文件中),Flex客户端只有通过服务端验证才能连接到一个destination,Blazeds使用底层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 commandBlazeds使用一个登录命令来检查证书和记录登录到服务器的用户。Blazeds包括了实现Tomcat,JBoss,BEA,WebLogic,WebSpher,JRUN等J2EE应用服务器的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连接上传输数据的安全版本的AMF和HTTP通道和端点 下面示例定义了一个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.jar,flex-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的配置。 ? 如何配置一个JDBCRealmA .在你的数据库中必须要有如下格式的两张表。用户表和关联的角色表,示例如下 用户表: 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配置的一些属性
示例: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&password=tzl" ??????userTable="users" userNameCol="userId" userCredCol="userPwd" userRoleTable="user_role" roleNameCol="role_name"/> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |