ss3ex中配置的Spring Security一直是单登陆口,现改成多登录口,坚持少写代码的原则,但是不管怎么样,必须要解决以下几个问题:
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" />标签
按照以上思路,可以实现无数个登录口。
分享到:
相关推荐
springboot+ spring security实现登录认证
spring security 基于oauth 2.0 实现 sso 单点登录Demo 使用 spring security 基于oauth 2.0 实现 sso 单点登录Demo spring boot + spring security + spring security oauth
用STS(Spring Tool Suite)开发的,spring mvc + spring security 实现的最简单的登录系统,无数据库。
spring-security多登录页面配置,包括前台和后台分开登录界面,注销登录返回不同的界面等。
NULL 博文链接:https://dreamzhong.iteye.com/blog/1722261
spring security + oauth 2.0 实现单点登录、认证授权,直接贴代码
1.本项目为SpringCloud Gateway的微服务框架,整合了SpringSecurity,微服务间使用Redis来获取登陆的用户信息。 2.由于Gat
该资源是springsecurity+oauth2+jwt实现的单点登录demo,模式为授权码模式,实现自定义登录页面和自定义授权页面。应用数据存在内存中或者存在数据库中(附带数据库表结构),token存储分为数据库或者Redis。demo...
项目中使用到的技术包含SpringBoot、SpringSecurity&oauth2(安全资源和授权中心模式、包括登录接口自定义返回字段、自定义手机号+密码登录、自定义免密登录)、Queue队列、线程池、xss攻击配置、SpringCache、Mybatis...
spring-security多个登录页面配置,分开了前台登录页面和后台登录页面登录,还有注销返回的不同的界面。
单点登录SSO解决方案之SpringSecurity+JWT实现.docx
springSecurity 实现登陆验证、传参,包括源代码和MYSQL的建库脚本。 传参的功能可以实现记录登陆之前打开的页面,登陆之后自动跳转到之前打开的页面。
SpringBoot+SpringSecurity整合示例代码,实现了从数据库中获取信息进行登录认证和权限认证。 本项目为idea工程,请用idea2019导入(老版应该也可以)。 本项目用户信息所需sql文件,在工程的resources文件夹下,...
应用中涉及到安全认证,目前项目有独立的统一认证网关,所以登录时只需要将安全认证网关的认证后信息塞到spring security中,由security3来管理用户的权限设置。目前项目由spring security2升级到spring security3。...
使用spring mvc 和spring security 完成简单的自定义登录
spring security spring security 中文文档
Spring-Security结合JWT 实现前后端分离完成权限验证功能案例,案例中,主要完成用户登录获取Token,通过Token访问Rest接口,没有权限或授权失败时返回JSON,前端根据状态码进行重新登录;案例中的用户名称: jake_j...
SpringBoot+SpringSecurity+JWT+MybatisPlus实现基于注解的权限验证,可根据注解的格式不同,做到角色权限控制,角色加资源权限控制等,粒度比较细化。 @PreAuthorize("hasAnyRole('ADMIN','USER')"):具有admin或...
Spring Security 演讲PPT(演讲嘉宾:张明星) WebSphere技术专家沙龙在广州圆满举办,WSC超级版主Fastzch(张明星)担任本次沙龙的演讲嘉宾,他给广州的WebSphere技术专家带来了以“Spring Security ”为主题的...
使用 spring security 基于oauth 2.0 实现 sso 单点登录Demo spring boot + spring security + spring security oauth