2010-09-28 136 views
26

嘿所有 我要讓註冊成功後自動登錄春天 含義: 我有一個受保護的頁面需要登錄才能訪問他們 和登記後,我想跳過登錄頁面,進行自動登錄,以便用戶可以看到受保護的頁面,找到了我? 我使用spring 3.0,spring security 3.0.2 怎麼辦?自動登錄

回答

38

這可以通過以下方式春季安全(半僞碼)來完成只包含如何在註冊後創建會話

+0

不正確的,我已經知道了着陸頁,但它要求用戶登錄纔可看到它,我不想去到登錄頁面,並希望使內部自動登錄,找到了我? – 2010-09-29 08:05:02

+0

我已更新我的代碼以在註冊後自動進行登錄。 – 2010-09-29 13:15:41

+0

我得到以下異常? org.springframework.security.authentication.BadCredentialsException:Bad credentials – 2010-10-13 11:11:52

-1

我不確定您是否要求這樣做,但在您的Spring Security配置中,您可以添加一個「記住我」標記。這將在您的客戶端管理一個cookie,所以下次(如果cookie尚未過期),您將自動登錄。

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

更新:

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

這不是嗯詢問 – 2010-09-28 14:25:36

8

只是一個關於如何autowire authenticationManager的第一個回覆評論。

你需要的時候,你在或者您的applicantion-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> 

此外,當您進行驗證,則可能引發的AuthenticationException ,所以你需要趕上它:

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但我遇到了一個棘手的問題時,實施它。

我的問題是,因爲我設置的註冊頁面有「沒有安全」,例如:

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

我認爲這不會造成SecurityContext的初始化,之後因此用戶註冊時,在服務器認證不能保存。

我不得不通過將其設定更改寄存器頁旁路進IS_AUTHENTICATED_ANONYMOUSLY

<http authentication-manager-ref="authMgr"> 
    <intercept-url pattern="/register/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> 
    ... 
</http> 
2
  1. 配置web.xml中允許Spring Security的處理向前進行登錄處理的URL。
  2. 處理註冊請求,例如創建用戶,更新ACL等。
  3. 用用戶名和密碼將其轉發到登錄處理URL以進行身份​​驗證。
  4. 獲得整個Spring Security過濾器鏈的好處,例如,會話固定保護。

由於轉發是內部的,因此在用戶看來,它們在用戶看來就像是在同一請求期間註冊和登錄一樣。

如果您的註冊表單中沒有包含正確的用戶名和密碼參數名稱,請將修改後的版本(使用HttpServletRequestWrapper)轉發給Spring Security登錄端點。

爲了達到這個目的,你必須修改你的web.xml,讓Spring Security過濾器鏈處理轉發給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> 

Source: mohchi blog

10

在Servlet的3+,你可以簡單地做request.login("username","password"),如果成功,重定向到任何你想要的頁面。你可以做同樣的自動註銷。

這裏是鏈接到該談論這個文檔的部分:http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#servletapi-3

+0

底層方法基本上是http://stackoverflow.com/a/3815189/1178781底下。所以,這對我來說非常合適! – justderb 2015-09-14 00:16:59

+0

非常感謝..這對我來說就像一個魅力.. – 2015-12-12 07:00:02

+0

完美的作品,它比任何其他答案簡單得多。謝謝! – LuTHieR 2016-05-25 08:57:24

0

這是回答上述問題的 在控制器:

@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中,所以人們不知道爲什麼邏輯不能在代碼運行時工作......並且在控制檯上沒有任何錯誤或異常。所以,如果你不會嘗試抓住它,你不會得到不良憑證的例外。

1

使用SecurityContextHolder.getContext()。setAuthentication(Authentication)完成工作,但它將繞過彈簧安全過濾器鏈,這將打開安全風險。

例如,在用戶重置密碼時可以說我的情況,我希望他不用再登錄就可以進入儀表板。當我使用上述方法時,它將我帶到儀表板,但它繞過了我已應用的併發過濾器,以避免併發登錄。這裏是一個沒有工作的一段代碼:

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

使用登錄處理的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 Security安全篩選器。

希望它有幫助

0

這是Servlet 3+集成的替代方案。如果你使用Spring Security的表單登錄,那麼你可以簡單地委託你的登錄頁面。例如:

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

假設你已經在你的形式usernamepassword領域,那麼「前進」會發送這些參數和Spring Security將使用這些認證。

我發現這種方法的好處是,您不會複製您的formLogindefaultSuccessUrl(下面的示例安全設置)。它還通過不需要HttpServletRequest參數來清理控制器。

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