2010-09-28 12 views
26

hej wszystkim chcę, aby auto logowanie po pomyślnej rejestracji na wiosnę znaczeniu: mam zabezpieczoną stronę, która wymaga logowania, aby uzyskać dostęp do nich i chcę po rejestracji, aby przejść na stronę logowania i zrobić automatyczne logowanie, aby użytkownik mógł zobaczyć tę chronioną stronę, ale mnie? Używam Spring 3.0, Spring Security 3.0.2 jak to zrobić?Automatyczne logowanie po udanej rejestracji

Odpowiedz

38

Można to zrobić z bezpieczeństwem sprężyny w następujący sposób (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); 
    } 
} 

Aktualizacja: tylko zawierać jak stworzyć sesję po zarejestrowaniu

+0

nie poprawne, już wiem stronę docelową, ale wymaga logowania, aby ją zobaczyć i nie chcę, aby przejść do strony logowania i chcesz, aby wewnętrzny Automatyczne logowanie, masz mnie ? –

+0

Zaktualizowałem swój kod, aby logować się automatycznie po rejestracji. –

+0

Mam następujący wyjątek ??? org.springframework.security.authentication.BadCredentialsException: Złe poświadczenia –

-1

Nie jestem pewien, czy pytasz o to, ale w konfiguracji Spring Security możesz dodać tag "remember-me". Spowoduje to zarządzanie plikiem cookie w twoim kliencie, więc następnym razem (jeśli ciasteczko nie wygasło) zostaniesz automatycznie zalogowany.

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

nie to um prośbą o –

8

Tylko skomentuj pierwszą odpowiedź na temat automatycznego uwierzytelniania menedżera uwierzytelniania.

Musisz ustawić alias gdy deklarujesz uwierzytelniania-manager w jednej Twój applicantion-servlet.xml lub ApplicationContext-security.xml pliku:

<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> 

Również podczas uwierzytelniania, może rzucić AuthenticationException , więc musisz go złapać:

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"; 
0

Spring Monkey's answer works great ale napotkałem problem podczas jego realizacji.

Mój problem był, bo ustawić stronę rejestracyjną mieć „bez zabezpieczenia”, np

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

myślę, że to nie powoduje SecurityContext zainicjowany, a więc po rejestrów użytkowników, uwierzytelniania w-serwerze nie mogą być zapisane.

musiałem zmienić obwodnicę stronę rejestr, ustawiając go w IS_AUTHENTICATED_ANONYMOUSLY

<http authentication-manager-ref="authMgr"> 
    <intercept-url pattern="/register/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> 
    ... 
</http> 
2
  1. Konfiguracja web.xml, aby umożliwić Wiosna zabezpieczeń do obsługi transakcji forward url przetwarzania logowania.
  2. Żądanie rejestracji uchwytu, np. utwórz użytkownika, zaktualizuj listę ACL itp.
  3. Przekaż dalej, podając nazwę użytkownika i hasło, aby przetwarzać adres URL logowania w celu uwierzytelnienia.
  4. Zyskaj korzyści z całego łańcucha filtrów Spring Security, np. zabezpieczenie sesji.

Ponieważ do przodu są wewnętrzne, pojawi się dla użytkownika tak, jakby były zarejestrowane i zalogowane podczas tego samego żądania.

Jeśli formularz rejestracyjny nie zawiera poprawnych nazw parametrów użytkownika i hasła, należy przekazać zmodyfikowaną wersję żądania (przy użyciu HttpServletRequestWrapper) do punktu końcowego logowania Spring Security.

Aby to zadziałało, musisz zmodyfikować plik web.xml, aby mechanizm łańcucha filtru Spring Security był przekazywany dalej dla login-processing-url. Na przykład:

<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> 

Source: mohchi blog

10

W Servlet 3+ można po prostu zrobić request.login("username","password") i jeśli się powiedzie, przekierowanie na stronę, co chcesz. Możesz zrobić to samo dla automatycznego wylogowania.

Oto link do sekcji dokumentacji, że rozmowy na ten temat: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#servletapi-3

+0

Podstawowa metoda polega w zasadzie na http://stackoverflow.com/a/3815189/1178781 pod maską. To zadziałało idealnie dla mnie! – justderb

+0

Wielkie dzięki. To zadziałało jak urok dla mnie .. –

+0

Działa idealnie i jest o wiele prostsze niż jakakolwiek inna odpowiedź. Dzięki! – LuTHieR

0

Jest to odpowiedź na powyższe pytanie kontroler:

@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; 
    } 

Ponadto powyższa metoda kontroler jest zdefiniowane jako:

`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"); 

    } 

Inne odpowiedzi nie sugerowały umieszczenia go w try/catch, więc nie zdajemy sobie sprawy, dlaczego logika nie działa, gdy działa kod ... i nic nie ma na konsoli ani błędu, ani wyjątku. Więc jeśli nie użyjesz go w próbie złapania, nie otrzymasz wyjątku od złych danych uwierzytelniających.

1

Użycie SecurityContextHolder.getContext(). SetAuthentication (Uwierzytelnianie) wykonuje zadanie, ale obejdzie łańcuch filtrów zabezpieczeń sprężyn, który otworzy ryzyko bezpieczeństwa.

Dla np. powiedzmy w moim przypadku, gdy użytkownik zresetował hasło, chciałem, aby wziął go na pulpit bez logowania. Kiedy użyłem powyższego podejścia, przenosi mnie do pulpitu nawigacyjnego, ale obejścił mój filtr współbieżności, który zastosowałem, aby uniknąć równoczesnego logowania. Oto fragment kodu, który spełnia swoje zadanie:

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

Zastosowanie atrybutu logowanie przetwarzania URL wraz z prostych zmian w web.xml

security-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> 

Dodanie tego fragmentu kodu w web.xml faktycznie wykonuje zadanie przekazania wyraźnego, przyszłego żądania, które wprowadzisz podczas automatycznego logowania i przekazania go do łańcucha filtrów bezpieczeństwa sprężynowego.

Nadzieja pomaga

0

Jest to alternatywa do apletu 3+ integracji. Jeśli używasz formularza logowania Spring Security, możesz po prostu przekazać swoją stronę logowania. Na przykład:

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

zakładając, że masz username i password pola w formularzu, a następnie „forward” wyśle ​​te parametry i wiosna Bezpieczeństwo użyje tych uwierzytelnić.

Korzyści wynikające z tego podejścia polegają na tym, że nie duplikuje się swojego formLogin 's defaultSuccessUrl (przykład poniższej konfiguracji zabezpieczeń). Czyści również kontroler, nie wymagając parametru HttpServletRequest.

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