0

我正在尝试创建一个应用程序,该应用程序仅允许用户在未登录时访问登录页面,而无法访问其他任何内容(减去资源)。一旦他们登录,我希望他们在注销之前无法访问登录页面,并且可以访问所有其他页面。现在,当我已经登录时,我的服务会记住我,但它仍然会让我访问登录页面。当我尝试在登录控制器上识别用户时,身份验证始终为空。

注意,我正在使用:Spring MVC 3 Hibernate 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>

如果可以的话请帮忙!我已经盯着这个太久了!!谢谢 :)

4

2 回答 2

0

您的登录似乎不太好,作为 spring 安全文档,您应该实现 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" />

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

于 2013-10-12T20:23:57.027 回答
0

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

  2. 第二个更改是修改“/login” URL 以映射到 permitAll。这再次意味着为映射到 permitAll 的请求填充了 SecurityContextHolder。

  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 会自动将 Principal 解析为HttpServletRequest.userPrincipal中的值。由于 Spring Security 在 Authentication 不是匿名的情况下将 HttpServletRequest.userPrincipal 替换为当前的 Authentication 对象,因此这对您来说是透明的。

于 2013-10-15T12:50:13.483 回答