Автоматический вход после успешной регистрации

Привет всем я хочу сделать автоматический вход после успешной регистрации в spring имея в виду: У меня есть защищенная страница, которая требует входа в систему для доступа к ним и я хочу, чтобы после регистрации пропустить страницу входа и сделать автоматический вход, чтобы пользователь мог видеть эту защищенную страницу, получил меня? Я использую spring 3.0, spring security 3.0.2 как это сделать?

Ответ 1

Это можно сделать с помощью безопасности spring следующим образом (semi-psuedocode):

import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;

@Controller
public class SignupController
{

    @Autowired
    RequestCache requestCache;

    @Autowired
    protected AuthenticationManager authenticationManager;

    @RequestMapping(value = "/account/signup/", method = RequestMethod.POST)
    public String createNewUser(@ModelAttribute("user") User user, BindingResult result,  HttpServletRequest request, HttpServletResponse response) {
        //After successfully Creating user
        authenticateUserAndSetSession(user, request);

        return "redirect:/home/";
    }

    private void authenticateUserAndSetSession(User user, HttpServletRequest request) {
        String username = user.getUsername();
        String password = user.getPassword();
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);

        // generate session if one doesn't exist
        request.getSession();

        token.setDetails(new WebAuthenticationDetails(request));
        Authentication authenticatedUser = authenticationManager.authenticate(token);

        SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
    }
}

Обновление: содержать только то, как создать сеанс после регистрации

Ответ 2

В Servlet 3+ вы можете просто сделать request.login("username","password") и в случае успеха перенаправить на любую страницу, которую вы хотите. Вы можете сделать то же самое для автоматического выхода из системы.

Вот ссылка на раздел документации, в котором говорится об этом: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#servletapi-3

Ответ 3

Просто комментарий к первому ответу о том, как сделать autwire authenticationManager.

Вам нужно установить псевдоним, когда вы объявляете диспетчер аутентификации в файле requestion-servlet.xml или applicationContext-security.xml:

<authentication-manager alias="authenticationManager>
    <authentication-provider>
        <user-service>
            <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
            <user name="bob" password="bobspassword" authorities="ROLE_USER" />
        </user-service>
    </authentication-provider>
</authentication-manager>

Кроме того, при аутентификации он может выдать исключение аутентификации, поэтому вам нужно его поймать:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
request.getSession();

token.setDetails(new WebAuthenticationDetails(request));

try{
    Authentication auth = authenticationManager.authenticate(token);

    SecurityContextHolder.getContext().setAuthentication(auth);
} catch(Exception e){
        e.printStackTrace();
}

return "redirect:xxxx.htm";

Ответ 4

  • Настройте web.xml, чтобы позволить Spring безопасности обрабатывать данные для URL-адреса для входа в систему.
  • Запрос на регистрацию ручек, например. создать пользователя, обновить ACL и т.д.
  • Переслать его с именем пользователя и паролем для URL-адреса входа в систему для аутентификации.
  • Получите преимущества цельной цепи Spring Защитный фильтр, например. защита фиксации сеанса.

Так как форварды являются внутренними, он будет отображаться для пользователя так, как если бы они были зарегистрированы и вошли в систему во время одного и того же запроса.

Если ваша регистрационная форма не содержит правильных имен параметров имени пользователя и пароля, отправьте измененную версию запроса (используя HttpServletRequestWrapper) в конечную точку доступа Spring.

Чтобы это сработало, вам нужно будет изменить ваш web.xml, чтобы маркер цепи безопасности Spring перешел вперед для login-processing-url. Например:

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<!-- Handle authentication for normal requests. -->
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Handle authentication via forwarding for internal/automatic authentication. -->
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/login/auth</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

Источник: блог mohchi

Ответ 5

Использование SecurityContextHolder.getContext(). setAuthentication (Authentication) выполняет задание, но оно обходит цепочку фильтров безопасности spring, которая откроет угрозу безопасности.

Например, скажем, в моем случае, когда пользователь reset пароль, я хотел, чтобы он забрал на приборную панель без входа снова. Когда я использовал вышеупомянутый подход, он выводит меня на панель мониторинга, но он обходит мой фильтр concurrency, который я применил, чтобы избежать параллельного входа. Вот фрагмент кода, который выполняет задание:

UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(empId, password);
Authentication auth = authenticationManager.authenticate(authToken);
SecurityContextHolder.getContext().setAuthentication(auth);

Использовать атрибут login-processing-url вместе с простым изменением в web.xml

безопасности XML

<form-login login-page="/login" 
            always-use-default-target="false" 
            default-target-url="/target-url" 
            authentication-failure-url="/login?error"
            login-processing-url="/submitLogin"/>

web.xml

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/submitLogin</url-pattern>
    <dispatcher>FORWARD</dispatcher>
 </filter-mapping>

Добавляя этот фрагмент кода в web.xml, на самом деле выполняется перенаправление вашего явного запроса на пересылку, который вы будете делать во время автоматического входа в систему и передачи его в цепочку фильтров безопасности spring.

Надеюсь, что это поможет

Ответ 6

Spring Ответ на обезьяну отлично работает, но я обнаружил сложную проблему при ее реализации.

Моя проблема состояла в том, что я установил на странице регистрации "нет безопасности", например:

<http pattern="/register/**" security="none"/>

Я думаю, что это не приводит к инициализации SecurityContext и, следовательно, после пользовательских регистров, аутентификация внутри сервера не может быть сохранена.

Мне пришлось изменить обход страницы регистрации, установив его в IS_AUTHENTICATED_ANONYMOUSLY

<http authentication-manager-ref="authMgr">
  <intercept-url pattern="/register/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
  ...
</http>

Ответ 7

Это ответ на предыдущий вопрос В контроллере:

@RequestMapping(value = "/registerHere", method = RequestMethod.POST)
    public ModelAndView registerUser(@ModelAttribute("user") Users user, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        System.out.println("register 3");

        ModelAndView mv = new ModelAndView("/home");
        mv.addObject("homePagee", "true");

        String uname = user.getUsername();

        if (userDAO.getUserByName(uname) == null) {

            String passwordFromForm = user.getPassword();
            userDAO.saveOrUpdate(user);

            try {
                authenticateUserAndSetSession(user, passwordFromForm, request);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


        }

        System.out.println("register 4");

        log.debug("Ending of the method registerUser");
        return mv;
    }

Далее описанный выше метод в контроллере определяется как:

`private void authenticateUserAndSetSession(Users user, String passwor`dFromForm, HttpServletRequest request){

        String username = user.getUsername();
        System.out.println("username:  " + username + " password: " + passwordFromForm);                        

        UserDetails userDetails = userDetailsService.loadUserByUsername(user.getUsername());

        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, passwordFromForm, userDetails.getAuthorities());
        request.getSession();

        System.out.println("Line Authentication 1");

        usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetails(request));

        System.out.println("Line Authentication 2");

        Authentication authenticatedUser = authenticationManager.authenticate(usernamePasswordAuthenticationToken);

        System.out.println("Line Authentication 3");


        if (usernamePasswordAuthenticationToken.isAuthenticated()) {
            SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
            System.out.println("Line Authentication 4");

        }

     request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());// creates context for that session.

        System.out.println("Line Authentication 5");

        session.setAttribute("username", user.getUsername());

        System.out.println("Line Authentication 6");

        session.setAttribute("authorities", usernamePasswordAuthenticationToken.getAuthorities());

        System.out.println("username:  " + user.getUsername() + "password: " + user.getPassword()+"authorities: "+ usernamePasswordAuthenticationToken.getAuthorities());

        user = userDAO.validate(user.getUsername(), user.getPassword());
        log.debug("You are successfully register");

    }

Другие ответы не предлагали помещать его в try/catch, поэтому никто не понимает, почему логика не работает, поскольку работает код... и ничего не происходит ни на ошибке, ни на консоли. Поэтому, если вы не ставите его в try catch, вы не получите исключение из-за плохих учетных данных.

Ответ 8

Это альтернатива интеграции сервлета 3+. Если вы используете учетную запись Spring Security form, вы можете просто делегировать ее на свою страницу входа в систему. Например:

@PostMapping("/signup")
public String signUp(User user) {
    // encode the password and save the user
    return "forward:/login";
}

Предполагая, что у вас есть поля username и password в вашей форме, тогда 'forward' отправит эти параметры, а Spring Security будет использовать те, которые будут аутентифицироваться.

Преимущество, которое я нашел с этим подходом, состоит в том, что вы не дублируете свой formLogin defaultSuccessUrl (пример настройки безопасности ниже). Он также очищает ваш контроллер, не требуя параметра HttpServletRequest.

@Override
public void configure(HttpSecurity http) {
    http.authorizeRequests()
            .antMatchers("/", "/signup").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login")
            .defaultSuccessUrl("/home", true)
            .permitAll();
}

Ответ 9

Я не уверен, если вы просите об этом, но в вашей конфигурации безопасности Spring вы можете добавить тег "запомнить-меня". Это будет управлять файлом cookie в вашем клиенте, поэтому в следующий раз (если файл cookie не истек), вы автоматически регистрируетесь.

<http>
    ...
    <remember-me />
</http>