Spring security:如果用户不满足特定条件,则使每个页面重定向
Posted
技术标签:
【中文标题】Spring security:如果用户不满足特定条件,则使每个页面重定向【英文标题】:Spring security : make every page redirect if the user doesn't meet a specific criteria 【发布时间】:2019-10-19 07:24:37 【问题描述】:我正在开发一个使用 Spring Security 作为身份验证/授权提供程序的 Web 应用程序。这是我的配置方式:
@Override
protected void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
//Allow resources for all pages
.antMatchers("/css/**", "/images/**", "/webjars/**").permitAll()
//Allow or disallow specific routes depending on user privileges
//Users
.antMatchers("/users/", "users/search").hasAuthority("View Users")
.antMatchers("/users/add", "/users/edit/*", "/users/delete/*").hasAuthority("Edit Users")
.antMatchers("/roles/", "roles/search").hasAuthority("View Roles")
.antMatchers("/roles/add", "/roles/edit/*", "/roles/delete/*").hasAuthority("Edit Roles")
.antMatchers("/permissions/", "permissions/search").hasAuthority("View Permissions")
//A million other antMatchers here...
//All custom routes require authentication
.anyRequest().authenticated()
//Custom login page and handling
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/perform_login")
.successHandler(loginHandler())
.failureUrl("/login_error")
.permitAll()
//Custom logout handling with POST request and logout handler for auditing
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessHandler(logoutHandler())
.logoutSuccessUrl("/logout_success")
.permitAll()
//Invalidate the session and delete the JSESSIONID cookie on logout
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
我不想发布太多代码(如果需要我会发布),但基本上我的用户存储在数据库中,我使用 UserDetails 和 UserDetailsService 的扩展来在 Spring Security 和 DB 之间进行交互。在我的用户实体中,我有一个布尔字段来控制用户是否需要更改他的密码(首次登录)。为了在用户登录时实现此功能,我有以下 AuthenticationSuccessHandler :
public class LoginHandler implements AuthenticationSuccessHandler
@Autowired
private UserService userService;
@Autowired
private PreferenceService preferenceService;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException
User user = userService.findById(((UserDetails) authentication.getPrincipal()).getId());
if (user.isMustChangePassword())
response.sendRedirect(request.getContextPath() + "/users/initialPasswordChange");
else
response.sendRedirect(request.getContextPath() + getAnchorPageURL(user));
这在登录时完美运行,行为正是我想要的。初始密码更改页面没有菜单,但没有任何东西可以阻止用户在不更改密码的情况下修改 URL 并登陆主页。在旧的 Spring MVC 时代,我会构建一个在每个页面上运行的自定义过滤器类,该类会检查登录的用户是否将该字段设置为 true 并重定向到初始密码更改页面。这样,无论用户做什么,在更改密码之前,整个站点都将无法访问。
现在有没有更优雅的 Spring Security 方式来做到这一点?
再次,如果有帮助,我将提供更多代码,不想淹没我的帖子,并希望首先包含最相关的部分。
【问题讨论】:
【参考方案1】:这适用于旧的 Spring MVC 过滤器方法。有没有更好、更纯粹的 Spring Security 方式来做到这一点?
@Component
@WebFilter(urlPatterns = "/*", description = "initialPasswordChangeFilter")
public class InitialPasswordChangeFilter implements Filter
@Autowired
private UserService userService;
@Override
public void init(FilterConfig fc) throws ServletException
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
Filter.super.init(fc);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
try
SecurityContextImpl sci = (SecurityContextImpl) req.getSession(false).getAttribute("SPRING_SECURITY_CONTEXT");
User user = userService.findById(((UserDetails) sci.getAuthentication().getPrincipal()).getId());
String url = req.getRequestURL().toString();
if (user.isMustChangePassword() && !url.contains("initial") && !url.contains("/webjars") && !url.contains("/css") &&
!url.contains("/js") && !url.contains("/images"))
res.sendRedirect(req.getContextPath() + "/users/initialPasswordChange");
else
chain.doFilter(request, response);
catch (NullPointerException ex)
chain.doFilter(request, response);
【讨论】:
以上是关于Spring security:如果用户不满足特定条件,则使每个页面重定向的主要内容,如果未能解决你的问题,请参考以下文章
Grails Spring Security 查询没有特定角色的用户
Spring Security with Spring Boot:使用过滤器时允许未经身份验证的用户访问特定端点
如果用户先前已授权访问,如何绕过 Spring security OAuth2 中的访问确认步骤?