Spring BlazeDS Integration之spring security(3)---自定义rememberMeServices,找到用户登陆成功切入点

仔细看过Spring BlazeDS Integration文档,我们知道,配置spring security其实很简单。

如下:

<flex:message-broker>
    <flex:secured />
</flex:message-broker>

即可。但是这小小的<flex:secured  /> 标记,其后台初始化了很多instance,其中最重要的就是

org.springframework.flex.security3.SpringSecurityLoginCommand    类,该类存在spring-flex-core-1.5.2.RELEASE.jar中,

之前提到过,等flex ui调用login api,请求会进入SpringSecurityLoginCommand.doAuthentication(String username, Object credentials)方法


我们来看看其具体实现:


    public Principal doAuthentication(String username, Object credentials) {
    	HttpServletRequest request = FlexContext.getHttpRequest();
    	HttpServletResponse response = FlexContext.getHttpResponse();
    	try {
    	    UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, extractPassword(credentials));
    	    setDetails(request, authRequest);
    	    
	        Authentication authentication = this.authManager.authenticate(authRequest);
	        if (authentication != null) {
	        	if (!isPerClientAuthentication() && request != null && response != null) {
	        		this.sessionStrategy.onAuthentication(authentication, request, response);
	        		this.rememberMeServices.loginSuccess(request, response, authentication); //注意这里
	        	}
	        	SecurityContextHolder.getContext().setAuthentication(authentication);
	        }
	        return authentication;
    	} catch (AuthenticationException ex) {
    	    SecurityContextHolder.clearContext();
    		if (request != null && response != null && !isPerClientAuthentication()) {
    			this.rememberMeServices.loginFail(request, response);
    		}
    		throw ex;
    	}
    }


可见此方法,让flex的login api 和spring sceurity 做了集成。让即使是flex ui传递过来的login请求也会走入到rememberMeServices当中去。

所以可以在rememberMeServices里做文章,找到用户登录成功后的切入点去,编写特殊逻辑。


修改security-config.xml:


<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">

	<http entry-point-ref="entryPoint">
		<anonymous enabled="false" />
		<form-login login-page="/login.jsp"
			authentication-success-handler-ref="simpleLoginSuccessHandler" />
		<remember-me key="testdrive" services-ref="rememberMeServices" />

	</http>

	<beans:bean id="rememberMeServices" class="test.MyRememberMeServices">
		<beans:property name="key" value="testdrive" />
		<beans:property name="alwaysRemember" value="true" />
	</beans:bean>

	<beans:bean id="entryPoint"
		class="org.springframework.flex.security3.FlexAuthenticationEntryPoint" />

	<beans:bean id="simpleLoginSuccessHandler" class="test.SimpleLoginSuccessHandler">
		<beans:property name="defaultTargetUrl" value="/secured/secured.html"></beans:property>
		<beans:property name="forwardToDestination" value="false"></beans:property>
	</beans:bean>

	<authentication-manager>
		<authentication-provider>
			<user-service>
				<user name="john" password="john" authorities="ROLE_USER" />
				<user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN" />
				<user name="guest" password="guest" authorities="ROLE_GUEST" />
			</user-service>
		</authentication-provider>
	</authentication-manager>

</beans:beans>


自定义的rememberMeServices如下:


package test;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.flex.samples.contact.IContactDAO;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;

public class MyRememberMeServices extends TokenBasedRememberMeServices {
	
	@Autowired
	private IContactDAO contactDAO;
	
	@Override
	public void onLoginSuccess(HttpServletRequest request,
			HttpServletResponse response,
			Authentication successfulAuthentication) {
		
		super.onLoginSuccess(request, response, successfulAuthentication);
		//SecurityContextHolder.getContext().setAuthentication(successfulAuthentication);
		System.out.println("Login Success:"+ contactDAO.findAll());  //登陆成功后,在这里实现自己的特殊逻辑
		
	}

}


注意:

  • rememberMeServices.loginSuccess(request, response, authentication); 不允许覆盖,
  • 但是loginSuccess()会调用onLoginSuccess() 方法,onLoginSuccess() 方法是允许覆盖的!
  • 自定义的rememberMeServices, 不管是http form提交,还是flex UI api提交,都会被调用。
  • 如果是http form提交,其调用顺序,会在<form-login login-page="/login.jsp"authentication-success-handler-ref="simpleLoginSuccessHandler" /> 之后被调用

特别注意,如果在MyRememberMeServices.onLoginSuccess()中,所调用的dao方法是,被spring security所管理的话,当通过flex ui 登陆时,是会抱错的:

“Caused by: org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext"

两个解决办法,任选其一:

  1. 所调用的dao方法,不被spring security管理控制,spring security管理控制dao的上一级service层。
  2. 或者,在调用dao方法之前,加上此语句:SecurityContextHolder.getContext().setAuthentication(successfulAuthentication);




PS:org.springframework.flex.security3.SpringSecurityLoginCommand    类 其实也可以继承

然后在自己订制化的LoginCommand类,去找到登陆成功后的切入点。但是本人感觉很复杂,还没研究明白。

具体请看:http://docs.spring.io/spring-flex/docs/1.5.x/reference/html/#custom-login-command





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值