Spring Security и действия, необходимые после входа в систему

Я пытаюсь реализовать экран действий, необходимых после входа пользователя в систему Spring Security? У меня есть требование, где пользователь должен выполнить, чтобы заполнить форму (изменить пароль, принять условия использования и т. д.), затем, как только пользователь завершит это действие, он может использовать остальную часть приложения. Я использую Spring OAuth2 с экраном входа в систему, который использует Spring Security flow.

до сих пор я пытался использовать http.formLogin().successHandler() который имеет пользовательскую реализацию SavedRequestAwareAuthenticationSuccessHandler, который определяет, есть ли у пользователя действие требуется, затем перенаправляет пользователя на страницу, когда он может заполнить форму, но проблема в том, что если пользователь переходит от страницы, он будет войти в приложение и может использовать его, не пропуская форме. Но я пытаюсь заблокировать пользователя от создания сеанса до тех пор, пока не будет завершена требуемая форма действия. После его завершения пользователь должен автоматически войти в систему (ex. если пользователь Треб. чтобы только согласиться с условиями использования, он должен войти в систему без ввод пароля второй раз)

вот код, который у меня есть до сих пор пользовательский обработчик:

public class CustomLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Autowired
    UserService userService;

    public final static String TARGET_URL_SESSION_ATTR_NAME = "target-url";

    public CustomLoginSuccessHandler(String defaultTargetUrl) {
        setDefaultTargetUrl(defaultTargetUrl);
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
        HttpSession session = request.getSession();


        AuthorityUser authorityUser = (AuthorityUser)authentication.getPrincipal();

        String userId = authorityUser.getUserId();

        User u = userService.getById(userId);

        Boolean changeRequiredDob = u.getChangeRequiredDob();
        Boolean changeRequiredPwd = u.getChangeRequiredPwd();
        Boolean changeRequiredTou = u.getChangeRequiredTou();

        if(changeRequiredDob || changeRequiredPwd || changeRequiredTou){

            String targetUrl = determineTargetUrl(request, response);
            session.setAttribute(TARGET_URL_SESSION_ATTR_NAME, targetUrl);
            getRedirectStrategy().sendRedirect(request, response, "/action-required");
        } else {
            super.onAuthenticationSuccess(request, response, authentication);
        }
    }
}

и затем, как только он будет успешно завершен, я перенаправляю пользователя на TARGET_URL_SESSION_ATTR_NAME Это было сохранено в сеансе.

было бы также полезно знать, как обнаружить и перенаправить пользователя на экран требуемых действий во время установленных сеансов (если пользователь вошел в систему и позже, когда он вошел в систему, администратор устанавливает флаг требуемых действий в своей учетной записи).

4 ответов


https://github.com/king-julien/spring-oauth2-customfilter Вот рабочий образец с авторизацией и сервером ресурсов. Этот сервер ресурсов (vanilla) является основным приложением без состояния, которое не будет продолжаться до тех пор, пока вы не примете условия обслуживания (чтобы принять TOS, просто сделайте сообщение на /TOS конечной точке) после аутентификации.

Создать фильтр

@Component
public class TosFilter extends OncePerRequestFilter{

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        System.out.println(request.getRequestURI());

        // In realworld scenario HelloWorldController.acceptedTOS is a persisted value rather than a static variable
        if(!HelloWorldController.acceptedTOS){
            //response.sendRedirect("/no-tos");
            request.getRequestDispatcher("error-no-tos").forward(request, response);
        }
        filterChain.doFilter(request,response);
    }
}

зарегистрируйте этот фильтр

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    TosFilter rolesFilter;

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception{

        httpSecurity
                .addFilterAfter(rolesFilter, AbstractPreAuthenticatedProcessingFilter.class)
                .csrf().disable()
                .authorizeRequests().anyRequest().permitAll();
    }
}

комментировать main с @EnableResourceServer.

@SpringBootApplication
@EnableResourceServer
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

способ, которым мы решаем это, чтобы страница утверждения OAuth2 была одностраничным приложением. По умолчанию контроллером страницы утверждения является WhitelabelApprovalEndpoint. Мы переопределяем это, определяя собственный контроллер OauthApproval, который переопределяет "/oauth / confirm_access", поэтому мы можем добавить дополнительные материалы к модели. При загрузке страницы утверждения (jsp) мы преобразуем некоторые свойства модели в переменные javascript (var token = '${_csrf.token}';) и запустите приложение AngularJS. Этот затем страница утверждения может делать все, что захочет (прежде чем показывать фактическую форму утверждения), нам просто нужно создать конечные точки REST для разных функций.

Не забудьте добавить @SessionAttributes ("authorizationRequest") в контроллер


вместо AuthenticationSuccessHandler вы должны использовать filter:

public class ActionRequirementCheckingFilter extends OncePerRequestFilter {

    /* This matcher should not match static resources (js,css etc),
     * url`s needed to handle the action and possibly something else,
     * depending on your application */
    private RequestMatcher matcher;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        HttpSession session = request.getSession();
        Boolean actionRequired = false;

        /* calculate actual value for actionRequired */

        if(matcher.matches(request) && actionRequired){

            /* save current request info into session for later use if needed */

            response.sendRedirect("/action-required");
        } else {
            filterChain.doFilter(request, response);
        }
    }

}

этот подход соответствует всем вашим требованиям:

  • пользователь не сможет перейти от него
  • пользователь будет автоматически вошел в систему после завершения действия
  • он будет работать даже для существующих сессий

единственным недостатком является то, что сеанс будет фактически создан до завершения действия, но если у вас нет реальной причины не делать этого (что я не могу даже изображение) это незначительно.


другой способ проверки прав доступа пользователя во время успешного сеанса входа в систему-через api фильтра

https://www.mkyong.com/spring-mvc/how-to-register-a-servlet-filter-in-spring-mvc/

затем вы можете реализовать функции, необходимые в doFilter () для проверки ваших правил.