springsecurity应用之支持URL传参登陆
项目中使用了spring security来做登陆的安全控制。按照官方文档弄好了。但是最近项目中又出来一个新需求,另外一个系统的用户,
需要用这样的模式来登录本系统:
http://url?username=test&password=test&returnurl=url
在别人的系统中,直接通过这三个参数,到我们的系统来查看某页面,虽然不情愿,但是也没有办法,唉,我们的系统式弱势系统,别人强势。NND。
查看了spring security的文档,同时也参考了一下源码,总算找到个解决方案:
主要查看和参考了源码中的这几个类:
ExceptionTranslationFilter
TargetUrlResolverImpl
AbstractProcessingFilter
AuthenticationProcessingFilter
其中最关键的类
AuthenticationProcessingFilter.java核心方法如下,这个方法主要是负责处理用户名和密码,由于那个强势系统要求传递过来的密码进行了BASE64加密,所以我要在这里BASE64解密一下
所以,我写了一个类似这个Filter的类,配置在配置文件上。
public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException {
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
HttpSession session = request.getSession(false);
if (session != null || getAllowSessionCreation()) {
request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextUtils.escapeEntities(username));
}
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
配置文件如下:
<beans:bean id="authenticationProcessingFilter"
class="cn.sccl.um.security.CustomerAuthenticationProcessingFilter">
<custom-filter before="AUTHENTICATION_PROCESSING_FILTER" />
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="authenticationFailureUrl" value="/user/login.do" />
<beans:property name="defaultTargetUrl" value="/portal/portal.do" />
<beans:property name="filterProcessesUrl" value="/jspringsecuritycheck.do" />
<beans:property name="usernameParameter" value="${security.username}" />
<beans:property name="passwordParameter" value="${security.password}" />
</beans:bean>
在我的CustomerAuthenticationProcessingFilter类中,和AuthenticationProcessingFilter代码相同,唯一就是加入了
拿到password后,再base64解密一下的代码。
然后跟代码,查看到TargetUrlResolverImpl关键类的核心方法:
public String determineTargetUrl(SavedRequest savedRequest, HttpServletRequest currentRequest,
Authentication auth) {
String targetUrl = currentRequest.getParameter(targetUrlParameter);
if (StringUtils.hasText(targetUrl)) {
try {
return URLDecoder.decode(targetUrl, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 not supported. Shouldn't be possible");
}
}
if (savedRequest != null) {
if (!justUseSavedRequestOnGet || savedRequest.getMethod().equals("GET")) {
targetUrl = savedRequest.getFullRequestUrl();
}
}
return targetUrl;
}
这就是决定登陆成功后,向哪个URL转向滴,一般就是默认配置在defaultTargetUrl里面。如果想自己根据传递过来的URL参数来决定转向页面,
那么这里类TargetUrlResolverImpl中的代码
public static String DEFAULT_TARGET_PARAMETER = "spring-security-redirect";
这就是接受这个URL的参数KEY。
那么最终,我们的URL接口就做成了如下:
http://localhost/jspringsecuritycheck.do?spring-security-redirect=reurl&j_username=test&j_password=MTExMTEx
如果URL参数里面的值有参数的,那么需要urlencode一下,比如形如这样的URL参数
http://localhost/workflow/excuteWorkitem4Oa.do?processInstId=111&name=test&type=1 会urlencode成这样:
http://localhost/workflow/excuteWorkitem4Oa.do?processInstId=111%26name%3Dtest%26type%3D1
项目中使用了spring security来做登陆的安全控制。按照官方文档弄好了。但是最近项目中又出来一个新需求,另外一个系统的用户,
需要用这样的模式来登录本系统:
http://url?username=test&password=test&returnurl=url
在别人的系统中,直接通过这三个参数,到我们的系统来查看某页面,虽然不情愿,但是也没有办法,唉,我们的系统式弱势系统,别人强势。NND。
查看了spring security的文档,同时也参考了一下源码,总算找到个解决方案:
主要查看和参考了源码中的这几个类:
ExceptionTranslationFilter
TargetUrlResolverImpl
AbstractProcessingFilter
AuthenticationProcessingFilter
其中最关键的类
AuthenticationProcessingFilter.java核心方法如下,这个方法主要是负责处理用户名和密码,由于那个强势系统要求传递过来的密码进行了BASE64加密,所以我要在这里BASE64解密一下
所以,我写了一个类似这个Filter的类,配置在配置文件上。
public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException {
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
HttpSession session = request.getSession(false);
if (session != null || getAllowSessionCreation()) {
request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextUtils.escapeEntities(username));
}
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
配置文件如下:
<beans:bean id="authenticationProcessingFilter"
class="cn.sccl.um.security.CustomerAuthenticationProcessingFilter">
<custom-filter before="AUTHENTICATION_PROCESSING_FILTER" />
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="authenticationFailureUrl" value="/user/login.do" />
<beans:property name="defaultTargetUrl" value="/portal/portal.do" />
<beans:property name="filterProcessesUrl" value="/jspringsecuritycheck.do" />
<beans:property name="usernameParameter" value="${security.username}" />
<beans:property name="passwordParameter" value="${security.password}" />
</beans:bean>
在我的CustomerAuthenticationProcessingFilter类中,和AuthenticationProcessingFilter代码相同,唯一就是加入了
拿到password后,再base64解密一下的代码。
然后跟代码,查看到TargetUrlResolverImpl关键类的核心方法:
public String determineTargetUrl(SavedRequest savedRequest, HttpServletRequest currentRequest,
Authentication auth) {
String targetUrl = currentRequest.getParameter(targetUrlParameter);
if (StringUtils.hasText(targetUrl)) {
try {
return URLDecoder.decode(targetUrl, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 not supported. Shouldn't be possible");
}
}
if (savedRequest != null) {
if (!justUseSavedRequestOnGet || savedRequest.getMethod().equals("GET")) {
targetUrl = savedRequest.getFullRequestUrl();
}
}
return targetUrl;
}
这就是决定登陆成功后,向哪个URL转向滴,一般就是默认配置在defaultTargetUrl里面。如果想自己根据传递过来的URL参数来决定转向页面,
那么这里类TargetUrlResolverImpl中的代码
public static String DEFAULT_TARGET_PARAMETER = "spring-security-redirect";
这就是接受这个URL的参数KEY。
那么最终,我们的URL接口就做成了如下:
http://localhost/jspringsecuritycheck.do?spring-security-redirect=reurl&j_username=test&j_password=MTExMTEx
如果URL参数里面的值有参数的,那么需要urlencode一下,比如形如这样的URL参数
http://localhost/workflow/excuteWorkitem4Oa.do?processInstId=111&name=test&type=1 会urlencode成这样:
http://localhost/workflow/excuteWorkitem4Oa.do?processInstId=111%26name%3Dtest%26type%3D1