Spring Security - 初始重定向到主页后能够返回登录页面

时间:2013-10-12 19:33:36

标签: hibernate spring-mvc groovy 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>

如果可以,请帮忙!我一直盯着这个太久了!!谢谢:))

2 个答案:

答案 0 :(得分:0)

你的登录似乎不太好,作为spring security Doc,你应该实现UserDetailsS​​ervice, 而不是获取参数,您的登录方法必须只有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" />

然而,在许多情况下,它完全取决于浏览器缓存,并且可能无法正常工作! 如果您在webserver XML中使用会话超时就足够了,并且不用担心会话毁坏。

答案 1 :(得分:0)

问题是您要映射到过滤器的/ login URL =&#34; none&#34;这意味着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,您可以在配置中拥有更多功能,并且可以声明允许任何用户使用&#34; permitAll&#34;来访问该资源。使用&#34; permitAll&#34;与filters="none"不同的是,Spring Security仍然对此请求进行操作,但允许任何用户访问该请求。这意味着将为映射到permitAll的请求填充SecurityContextHolder。

  2. 第二个变化是修改&#34; / login&#34;要映射到permitAll的URL。同样,这意味着为映射到permitAll的请求填充了SecurityContextHolder。

  3. 最后一个更改是更新了其他访问属性,以便它们可以使用use-expressions =&#34; true&#34;更改。特别是&#34; ROLE_USER&#34;不管用。相反,你必须声明&#34; hasRole(&#39; ROLE_USER&#39;)&#34;代替。

  4. 我还会考虑使用以下内容而不是直接访问身份验证。这可以确保您没有与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 PrincipalHttpServletRequest.userPrincipal中的值{{3}}。由于当身份验证不是匿名时,Spring Security会将HttpServletRequest.userPrincipal替换为当前的身份验证对象,因此这对您来说是透明的。