2013-10-12 63 views
0

我正在嘗試創建一個應用程序,它允許用戶在登錄時只能訪問登錄頁面,並且無權訪問其他任何東西(減去資源)。登錄後,我希望他們在登出之前無法訪問登錄頁面,並可訪問所有其他頁面。目前,我的服務在我已經登錄時會記住我,但它仍然會讓我訪問登錄頁面。當我嘗試在登錄控制器上識別用戶時,身份驗證始終爲空。Spring Security - 能夠在初始重定向到主頁後返回登錄頁面

注意,我使用的是: Spring MVC的3 休眠4 的Groovy 2.1

這裏是我的登錄控制器:

@RequestMapping(method = RequestMethod.GET) 
String login(Model model, @RequestParam(value="account", required=false) String account, @RequestParam(value="uuid", required=false) String uuid, @RequestParam(value="message", required=false) String message) { 
    addStatusAttribute(model, account, uuid, message) 
    model.addAttribute("newUser", new User()) 
    Authentication auth = SecurityContextHolder.context.authentication 
    if (auth != null) { 
     logger.info(auth.name) 
    } 
    else { 
     logger.info(auth) // Always hits here 
    } 
    if (!(auth instanceof AnonymousAuthenticationToken) && auth != null) { 
     "forward:/home" 
    } 
    else { 
     "login" 
    } 

這裏是我的安全配置:

<http auto-config="true"> 
      <intercept-url pattern ="/login**" filters="none"/> 
    <intercept-url pattern="/static/**" filters="none" /> 
    <intercept-url pattern="/**" access="ROLE_USER" /> 
    <form-login login-page="/login" default-target-url="/home" 
     authentication-failure-url="/login?error=true" 
     always-use-default-target="true" /> 
    <logout logout-success-url="/login" /> 
    <remember-me data-source-ref="dataSource" 
     user-service-ref="myUserDetailsManager" 
     token-validity-seconds="864000" 
     key="skyfury_key"/> 
</http> 

我不要認爲這有什麼問題,但這裏是我的JSP表單:

    <form method="POST" action="<c:url value="/j_spring_security_check" />"> 
       <input type="text" name="j_username" placeholder="Email" /> 
       <input type="password" name="j_password" placeholder="Password" /> 
       <label for="j_remember">Remember Me</label> 
       <input id="j_remember" type='checkbox' name='_spring_security_remember_me' value="on" /> 
       <input type="submit" value="Login" /> 
      </form> 

如果可以的話請幫忙!我一直盯着這太久了!謝謝:)

回答

0

問題是,您映射到filters =「none」的/ login URL意味着SecurityContext和Authentication將不可用於該URL。試着改變你的配置,如下圖所示:

<http auto-config="true" use-expressions="true"> 
    <intercept-url pattern ="/login**" access="permitAll"/> 
    <intercept-url pattern="/static/**" access="permitAll" /> 
    <intercept-url pattern="/**" access="hasRole('ROLE_USER')" /> 
    <form-login login-page="/login" default-target-url="/home" 
     authentication-failure-url="/login?error=true" 
     always-use-default-target="true" /> 
    <logout logout-success-url="/login" /> 
    <remember-me data-source-ref="dataSource" 
     user-service-ref="myUserDetailsManager" 
     token-validity-seconds="864000" 
     key="skyfury_key"/> 
</http> 

你會發現我做了三個轉變:

  1. 首先,我要指出use-expressions="true"。這使您可以使用SpEL in the access attribute。通過允許SpEL,您可以在配置中擁有更多的權力,並且可以聲明允許任何用戶使用「permitAll」訪問資源。使用「permitAll」與filters="none"的不同之處在於Spring Security仍然對此請求進行操作,但允許任何用戶訪問請求。這意味着爲映射到permitAll的請求填充SecurityContextHolder。

  2. 第二個變化是修改要映射到permitAll的「/ login」URL。這也意味着SecurityContextHolder被填充爲映射到permitAll的請求。

  3. 最後一項更改是更新了其他訪問屬性,以便它們可以與use-expressions =「true」更改一起使用。特別是「ROLE_USER」不起作用。相反,您必須聲明「hasRole('ROLE_USER')」。

我還會考慮使用以下內容,而不是直接訪問認證。這可以確保您與Spring Security緊密結合。

@RequestMapping(method = RequestMethod.GET) 
String login(Principal principal, Model model, @RequestParam(value="account", required=false) String account, @RequestParam(value="uuid", required=false) String uuid, @RequestParam(value="message", required=false) String message) { 
    ... 

    logger.info(principal?.name) 

    if (principal != null) { 
     "forward:/home" 
    } 
    else { 
     "/login" 
    } 
} 

這工作,因爲Spring MVC的將automatically resolve the Principal的價值HttpServletRequest.userPrincipal找到。由於Spring Security在身份驗證不是匿名的情況下將HttpServletRequest.userPrincipal替換爲當前的Authentication對象,因此透明地爲您工作。

+0

哦哇這實際上解決了我的問題!非常感謝!!!!!!!!!!!!!!!! – tomskytwo

0

登錄似乎沒有得到很好的,隨着春天的安全文件,你應該實現的UserDetailsS​​ervice, 而不是讓PARAM和您的登錄方法必須具有隻是ModelMap而不是任何參數,可以看到 例如:http://aykutakin.wordpress.com/2013/07/08/spring-security-spring-custom-authentication-provider/ 的註銷也您可以使會話失效

<logout delete-cookies="JSESSIONID" invalidate-session="true" 
    logout-success-url="/login.do" /> 

但是在許多情況下,它完全依賴於瀏覽器緩存,並且可能無法正常工作! 如果您在Web服務器XML中使用會話超時並且不用擔心會話銷燬。

相關問題