Spring MVC+BlazeDS+Flex框架实践:Security篇
在Spring MVC+BlazeDS+Flex框架实践:Database篇的基础上,这次要加入的是Spring Security的配置与应用。至于Spring Security的原理及配置详解网上已经有很多可参考的文章,在这里就不再重复了。
一、Spring Security配置
1)添加Application-Security.xml
在JAVA工程src下创建Application-Security.xml
<authentication-provider user-service-ref=”customUserDetailsService”>
</authentication-provider>
<beans:bean id=”loggerListener” class=”com.hand.common.security.SecurityLogListener”>
<beans:property name=”genericService” ref=”genericService” />
</beans:bean>
<beans:bean id=”customLogoutFilter” class=”org.springframework.security.ui.logout.LogoutFilter”>
<custom-filter before=”LOGOUT_FILTER” />
<beans:constructor-arg value=”/”></beans:constructor-arg>
<beans:constructor-arg>
<beans:list>
<beans:bean class=”com.hand.common.security.SecurityLogoutHandler”>
<beans:property name=”genericService” ref=”genericService” />
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id=”customUserDetailsService” class=”com.hand.common.security.FlexUserDetailsService”>
<beans:property name=”genericService” ref=”genericService”></beans:property>
<beans:property name=”userNameProperty”>
<beans:value>userName</beans:value>
</beans:property>
</beans:bean>
</beans:beans>
2)修改web.xml
在添加Application-Security.xml后,需要在web.xml中将其添加到初始化加载列表中
修改web.xml以下配置:
二、Security类创建
在JAVA工程src下创建package com.common.security
创建SecurityLogListener.java
System.out.println(“Username: “+((FlexUserDetails) obj).getUsername());
System.out.println(“Login Date: “+new Date());
System.out.println(“Session Id: “+FlexContext.getFlexSession().getId());
}
} else if (event instanceof InteractiveAuthenticationSuccessEvent)
logger.warn(“InteractiveAuthenticationSuccessEvent:” + authEvent.getAuthentication().getDetails());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if (event instanceof HttpSessionApplicationEvent) {
HttpSessionApplicationEvent sessionEvent = (HttpSessionApplicationEvent) event;
if (event instanceof HttpSessionDestroyedEvent) {
logger.info(“[destroy]”+sessionEvent.getSession().getId());
Map<String, Object> params = new HashMap<String, Object>();
params.put(“sessionId”, sessionEvent.getSession().getId());
System.out.println(“Session Id: “+sessionEvent.getSession().getId());
System.out.println(“Session remove date: “+new Date());
}else
logger.info(“[create]”+sessionEvent.getSession().getId());
}
}
}
创建SecurityLogoutHandler.java
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.logout(httpservletrequest, httpservletresponse, authentication);
}
}
创建FlexUserDetails.java
此类中的信息与数据库的结构有关
}
public GrantedAuthority[] getAuthorities() {
return authorities;
}
public String getPassword() {
return fu.getUserPassword();
}
public String getUsername() {
// TODO Auto-generated method stub
return fu.getUserName();
}
public boolean isAccountNonExpired() {
return true;
}
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
public boolean isEnabled() {
Date now=new Date();
return fu.getStartDateActive().before(now)&&(fu.getEndDateActive()==null||fu.getEndDateActive().after(now));
}
public FrameworkUser getFu() {
return fu;
}
public void setFu(FrameworkUser fu) {
this.fu = fu;
}
public void setAuthorities(GrantedAuthority[] authorities) {
this.authorities = authorities;
}
}
创建FlexUserDetailsService.java
此类中具体执行了用户登录时的授权等操作,其中明确了当用户为”admin”时,为其授予ROLE_ADMIN、ROLE_USER、ROLE_ANONYMOUS权限;而其他用户则只有ROLE_USER、ROLE_ANONYMOUS权限。不同权限的访问范围在Application-Security.xml中进行控制。本例中只有ROLE_ADMIN权限的角色才能访问modules/admin下的页面。
List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
if(name.equals(“admin”)){
roles.add(new GrantedAuthorityImpl(name));
roles.add(new GrantedAuthorityImpl(“ROLE_ANONYMOUS”));
roles.add(new GrantedAuthorityImpl(“ROLE_ADMIN”));
roles.add(new GrantedAuthorityImpl(“ROLE_USER”));
System.out.println(“授权: ROLE_ADMIN,ROLE_ANONYMOUS”);
}else{
roles.add(new GrantedAuthorityImpl(name));
roles.add(new GrantedAuthorityImpl(“ROLE_ANONYMOUS”));
roles.add(new GrantedAuthorityImpl(“ROLE_USER”));
System.out.println(“授权: ROLE_USER,ROLE_ANONYMOUS”);
}
GrantedAuthority[] authoritiesarray = new GrantedAuthority[roles.size()];
roles.toArray(authoritiesarray);
return authoritiesarray;
}
}
创建AuthenticationHelper.java
此类在用户登录时被调用
三、配置AuthenticationHelper
1)发布AuthenticationHelper
在Application-Flex.xml中添加如下配置:
2)创建CommonModule.mxml
在FLEX工程modules/common目录下创建CommonModule.mxml,用以实现Security验证
3)引用authenticationHelper
在FLEX工程remoting-config.xml中添加如下配置:
3)修改Index.mxml
在Index.mxml中调用authenticationHelper,修改后的Index.mxml内容如下:
<mx:Script>
<!–[CDATA[
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
private function initApp():void{
UserService.getMessage();
UserService.getMessage.addEventListener(ResultEvent.RESULT, getMessageHandler);
}
private function getMessageHandler(evt:ResultEvent):void{
UserService.getMessage.removeEventListener(ResultEvent.RESULT, getMessageHandler);
initText.text = evt.result as String;
}
private function login():void{
//添加登录成功监听器
authenticationHelper.authenticatePrincipal.addEventListener(ResultEvent.RESULT, loginSuccess);
//添加登录失败监听器
authenticationHelper.authenticatePrincipal.addEventListener(FaultEvent.FAULT, loginFailure);
//向服务器发送登录请求
authenticationHelper.authenticatePrincipal(username.text, password.text);
}
private function loginSuccess(event:Event):void
{
authenticationHelper.authenticatePrincipal.removeEventListener(ResultEvent.RESULT, loginSuccess);
this.currentState=’loginSuccess’;
}
private function loginFailure(event:FaultEvent):void
{
Alert.show(“登录不成功!”+event.fault.faultString);
authenticationHelper.removeEventListener(FaultEvent.FAULT, loginFailure);
}
private function changeState(sign:String):void{
currentState = ‘moduleState’;
if(sign==’A’){
currentState = ‘moduleState’;
moduleLoader.url = ‘../admin/UserModule.swf’;
}else{
currentState = ‘moduleState’;
moduleLoader.url = ‘../common/CommonModule.swf’;
}
}
private function logout():void{
navigateToURL(new URLRequest(“javascript:location.href=’TestProject/j_spring_security_logout’;”), “_self”);
}
]]–>
</mx:Script>
<mx:RemoteObject id=”UserService” destination=”UserService”/>
<mx:RemoteObject id=”authenticationHelper” destination=”authenticationHelper”/>
<mx:states>
<mx:State name=”loginSuccess”>
<mx:RemoveChild target=”{vbox1}”/>
<mx:AddChild position=”lastChild”>
<mx:VBox width=”50%” height=”30%” horizontalAlign=”center” verticalAlign=”middle”>
<mx:LinkButton label=”admin.mxml” click=”changeState(‘A’)”/>
<mx:LinkButton label=”common.mxml” click=”changeState(‘B’)”/>
</mx:VBox>
</mx:AddChild>
</mx:State>
<mx:State name=”moduleState”>
<mx:RemoveChild target=”{vbox1}”/>
<mx:AddChild position=”lastChild”>
<mx:ModuleLoader width=”50%” height=”50%” id=”moduleLoader” url=”../admin/UserModule.swf”/>
</mx:AddChild>
<mx:AddChild position=”lastChild”>
<mx:LinkButton label=”返回” click=”currentState=’loginSuccess'”/>
</mx:AddChild>
<mx:AddChild position=”lastChild”>
<mx:LinkButton label=”退出” click=”logout()”/>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:Label text=”Welcome” id=”initText” fontWeight=”bold”/>
<mx:VBox width=”50%” height=”50%” horizontalAlign=”center” verticalAlign=”middle” id=”vbox1″>
<mx:FormItem label=”用户名” labelWidth=”100″>
<mx:TextInput id=”username” width=”200″/>
</mx:FormItem>
<mx:FormItem label=”密码” labelWidth=”100″>
<mx:TextInput id=”password” width=”200″ displayAsPassword=”true”/>
</mx:FormItem>
<mx:Button label=”登录” width=”80″ click=”login()”/>
</mx:VBox>
</mx:Application>
四、编译运行
1)编译FLEX工程
选择Project—>Clean—>TestProject
2)拷贝FLEX编译目录bin-debug/modules到JAVA工程WebRoot下
3)启动本地数据库
4)启动服务器
5)服务器正常启动后,在浏览器内输入(其中9090为服务器端口号)
http://localhost:9090/TestProject/modules/common/Index.html
运行结果:
以Sky用户登录
登录首页
查看modules/admin/UserModule.swf,由于权限控制将无法访问
查看modules/common/CommonModule.swf
以admin用户登录
查看modules/admin/UserModule/swf,由于已经为该用户授予了权限,因此可以访问
查看modules/common/CommonModule.swf
到此Spring MVC+BlzeDS+Flex框架的搭建三个过程都已经结束,如果今后还有新的内容我会及时和大家分享。