1、用户未登录:访问权限页面,访问非权限页面
2、用户登录:访问权限页面(权限不够)
3、密码错误返回页面
4、注销页面
一个个问题来解决,第一个问题,用户未登录时访问访问非权限页面,直接就过了。麻烦的就是访问有权限的页面,因为Spring Security会使用AuthenticationEntryPoint在未登录用户访问被保护资源时自动跳转到登录页面,所以我们这里需要的就是扩展AuthenticaitonEntryPoint。
修改spring_security.xml文件:
<http auto-config="true" access-denied-page="/common/403.htm"
entry-point-ref="loginPageEntryPoint">
<intercept-url pattern="/login.**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/loginfont.**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
……
<beans:bean id="loginPageEntryPoint" class="com.security.resource.LoginPageEntryPoint">
<beans:property name="loginPageStrategy" ref="urlMappingLoginPageStrategy" />
</beans:bean>
<beans:bean id="urlMappingLoginPageStrategy"
class="com.security.resource.UrlMappingLoginPageStrategy" />LoginPageEntryPoint.java文件:
package com.security.resource;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.AuthenticationException;
import org.springframework.security.ui.AuthenticationEntryPoint;
import org.springframework.util.Assert;
public class LoginPageEntryPoint implements AuthenticationEntryPoint,
InitializingBean {
private LoginPageStrategy loginPageStrategy;
public void afterPropertiesSet() throws Exception {
Assert.notNull(loginPageStrategy,
"loginPageStrategy must be specified");
}
public void commence(ServletRequest request, ServletResponse response,
AuthenticationException authException)
throws IOException, ServletException {
loginPageStrategy.process((HttpServletRequest) request,
(HttpServletResponse) response);
}
public void setLoginPageStrategy(LoginPageStrategy loginPageStrategy) {
this.loginPageStrategy = loginPageStrategy;
}
}LoginPageStrategy.java 接口文件:package com.security.resource;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface LoginPageStrategy {
void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException;
}UrlMappingLoginPageStrategy.java文件:package com.security.resource;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UrlMappingLoginPageStrategy implements LoginPageStrategy {
public void process(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
String targetUrl = null;
String uri = request.getRequestURI();
if (uri.indexOf("system") != -1) {
targetUrl = "/login.jsp";
} else {
targetUrl = "/loginfont.jsp";
}
targetUrl = request.getContextPath() + targetUrl;
response.sendRedirect(targetUrl);
}
}备注:别忘了在login.jsp同目录下复制一个jsp文件,取名叫loginfont.jsp。这2个文件代表着2个不同的登录口,表单提交的地址都是action="${base}/j_spring_security_check"。另外,因为多了一个登陆页面,他的权限也要放开,见上面修改的spring_security.xml文件。第二个问题的解决方案有2个,分别是扩展AuthenticationProcessFilter,拦截403错误,还是根据url来判断跳转到不同的页面,这个方案我写了个类,开始抱着一定要实现的目的,由于逻辑上很多地方分散了,不好全部集中处理,后来觉得很麻烦,于是就放弃了。第二个方案相对来说,简单些,就是在用户登录时,往session中写进一个状态,如果不用session就用ThreadLocal,然后修改access-denied-page="/common/403.htm" 把这个页面改成一个action或者jsp的地址,在其中提取session中的值进行判断,跳转到不同的无权限错误页面。用户登录时写session有2个方案,一是,直接在ss3ex 中我配置的密码过滤器中操作(这个比较简单)。还有一个就是lingo介绍的自定义过滤器,他实现的步骤是:
添加spring_security.xml 文件
<!-- 自定义过滤器,刚开始由于没有配置authenticationFailureUrl属性,导致用户密码错误出错后,跳转页面不正常-->
<beans:bean id="loginFilter" class="com.security.resource.LoginFilter">
<!-- 放置在AUTHENTICATION_PROCESSING_FILTER的前面-->
<custom-filter before="AUTHENTICATION_PROCESSING_FILTER" />
<!-- 认证-->
<beans:property name="authenticationManager" ref="authenticationManager" />
<!-- 认证错误页面-->
<beans:property name="authenticationFailureUrl" value="/login.jsp?error=1" />
<!-- 认证成功页面,必须的-->
<beans:property name="defaultTargetUrl" value="/demo/success.shtml" />
</beans:bean>LoginFilter.java 文件:package com.security.resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
import com.utils.FakeSession;
public class LoginFilter extends AuthenticationProcessingFilter {
public Authentication attemptAuthentication(HttpServletRequest request)
throws AuthenticationException {
Authentication authentication = super.attemptAuthentication(request);
//状态, admin表示后台,font表示前台
String status = null;
String uri = request.getRequestURI();
if (uri.indexOf("system") != -1) {
status = "admin";
} else {
status = "font";
}
FakeSession.messageSegment.set(status);
return authentication;
}
}FakeSession类(仿session)见我博客的另一篇文章。第三个问题的解决方案,思路已经在第二个问题中解决了
<!-- 认证错误页面-->
<beans:property name="authenticationFailureUrl" value="/login.jsp?error=1" /> 不过这里要修改下login.jsp,按照第二个问题的思路,写个判断的条件,根据ThreadLocal中status的状态跳转到不同的页面。
第四个问题的解决方案,注销页面,<logout logout-success-url="/login.jsp" invalidate-session="true" /> 也是修改这个页面,已经在第三个问题中解决了。
末:感谢狂人和lingo,提供的security的帮助,感谢小鸟提供的ThreadLocal。
老是有人问,再说详细点,补充如下(源代码在ss3ex中):
spring security2的流程
Spring Security会使用AuthenticationEntryPoint在未登录用户访问被保护资源时自动跳转到登录页面,自定义过滤器扩展AuthenticationProcessingFilter过滤器实现登录后,跳转页面前的后续操作,比如可以实现在跳转页面前往session中写入些内容。
Spring Security2多登录口实现
1、前后台登录页面;扩展AuthenticationEntryPoint过滤器
2、前后台认证成功页面;自定义过滤器扩展AuthenticationProcessingFilter过滤器
3、前后台认证失败页面;自定义过滤器扩展AuthenticationProcessingFilter过滤器
4、前后台无权限页面; access-denied-page
5、前后台注销返回页面。配置<logout logout-success-url="/login.jsp" invalidate-session="true" />标签
按照以上思路,可以实现无数个登录口。
2526



被折叠的 条评论
为什么被折叠?



