【问题标题】:Spring security : make every page redirect if the user doesn't meet a specific criteriaSpring security:如果用户不满足特定条件,则使每个页面重定向
【发布时间】: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 和 UserDetailsS​​ervice 的扩展来在 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 方式来做到这一点?

再次,如果有帮助,我将提供更多代码,不想淹没我的帖子,并希望首先包含最相关的部分。

【问题讨论】:

    标签: java authentication redirect spring-security filter


    【解决方案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);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-30
      • 1970-01-01
      • 2021-07-26
      • 2023-02-22
      • 2018-11-13
      • 1970-01-01
      相关资源
      最近更新 更多