由于种种关系,虽然spring security 3出了很久了,但还是项目中只能用
spring security 2,发现spring security 2真是十分多东西了,
其中比如象在struts2中和轻易写的session管理等,在spring security 2中都要
仔细研究文档,花点心思,这里首先推荐两篇网上为数不多的spring security2
的中文文档给大家学习,还有代码,先看这两篇:
http://www.blogjava.net/redhatlinux/archive/2008/08/20/223148.html
http://www.blogjava.net/redhatlinux/archive/2008/09/01/226010.html
然后看完这两篇后,就可以开始吧。首先要解决的问题,是如何登录后,保存用户的session,其实这个可以
替换掉spring security 2中的authenticationProcessingFilter。
先来看下application-security.xml的配置文件,注意本文说的依然是2的配置
首先是开始部分:
注意,这里要把auto-config设置为false,并且同时要删除原先的:
<ss:form-login login-page="/login.action"
authentication-failure-url="/login.action?error=true"
default-target-url="/" always-use-default-target="true" />
再来看下这个插入点:
<bean id="authenticationProcessingFilterEntryPoint"
class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.action" />
<property name="forceHttps" value="false" />
</bean>
接下来,建立自定义的类MyAuthenticationProcessingFilter,代码如下:
ublic class MyAuthenticationProcessingFilter extends
AuthenticationProcessingFilter {
protected void onSuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, Authentication authResult)
throws IOException {
super.onSuccessfulAuthentication(request, response, authResult);
Object obj = SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
if (obj instanceof UserDetails) {
userId = ((UserInfo) obj).getUserid();
username= ((UserInfo) obj).getUsername();
}
request.getSession().setAttribute("userId", userId);
}
可以看到,继承了AuthenticationProcessingFilter就可以了,在
onSuccessfulAuthentication方法中,可以进行session的保存了!
接下来要在配置文件中进行配置,注册替换掉原来的,如下:
<ss:logout logout-success-url="/login.action" />
<ss:authentication-manager alias="authenticationManager" />
<bean id="authenticationProcessingFilter"
class="com.liao.security.MyAuthenticationProcessingFilter">
<ss:custom-filter before="AUTHENTICATION_PROCESSING_FILTER" />
<property name="defaultTargetUrl" value="/" />
<property name="filterProcessesUrl" value="/j_spring_security_check" />
<property name="authenticationFailureUrl" value="/login.action?error=true" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
可以看到,其实就是我们自定义的过滤器,摆放在spring security 2中的
AUTHENTICATION_PROCESSING_FILTER前面了;
这样,我们就完成了第一个功能,可以在spring security 2中试用session了!
2) 显示没有权限的页面
当没有权限的页面时,一般的显示方法是
<ss:http auto-config="false" access-denied-page="/common/403.jsp">
但又有资料说到,如果要动态,不用一个固定的403.jsp的话,可以自定义
access-denied-handler,于是实验了下,用的是spring 2.5+spring security 2.0.4,
<bean id="exceptionTranslationFilter"
class="org.springframework.security.ui.ExceptionTranslationFilter">
<property name="accessDeniedHandler" ref="accessDeniedHandler" />
<property name="authenticationEntryPoint" ref="authenticationProcessingFilterEntryPoint" />
</bean>
<!-- 处理AccessDeniedException -->
<bean id="accessDeniedHandler" class="org.springframework.security.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/common/403.jsp" />
</bean>
但很遗憾,<bean id="accessDeniedHandler" class="org.springframework.security.ui.AccessDeniedHandlerImpl">
这里尽管用了自定义的类,依然不起效果,依然出现access denied的页面,
没办法,只好依然用access-denied-page="/common/403.jsp">,只不过
在403.jsp中,用一个重定向,就可以重新定向到比如struts2.action去自由发挥拉
3 session超时
spring security 3中提供了相关的配置设置,但可惜2中没有,
只有继续动手,首先,要在web.xml中,将自定义的filter放在spring security 2的
fiter前,比如
<filter>
<filter-name>SessionTimeoutFilter</filter-name>
<filter-class>com.liao.security.SessionTimeoutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionTimeoutFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
然后代码中:
public class SessionTimeoutFilter implements Filter {
private String str;
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
HttpSession session = servletRequest.getSession();
String url = servletRequest.getRequestURI();
String path = url.substring(url.lastIndexOf("/"));
if (path.indexOf("login.action") == -1 && path.indexOf(".action") != -1) {
if (session.getAttribute("userId") == null) {
str = "<script language='javascript'>alert('登录超时,请重新登录');"
+ "window.top.location.href="+"'"+servletRequest.getContextPath()+"/login.action"+"';"+
"</script>";
response.setContentType("text/html;charset=UTF-8");// 解决中文乱码
try {
PrintWriter writer = response.getWriter();
writer.write(str);
writer.flush();
writer.close();
} catch (Exception e) {
}
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
}
这里要判断,如果加载的不是login.action或者加载的不是.action结尾的(比如一些资源文件等)的,就要判断其中session是否null了,null的话跳转,
总体来说,功能就实现了
转载于:http://jackyrong.iteye.com/blog/1584303