Spring mvc / security:从spring security中排除登录页面

Posted

技术标签:

【中文标题】Spring mvc / security:从spring security中排除登录页面【英文标题】:Spring mvc / security : excluding the login page from spring security 【发布时间】:2014-01-19 09:45:20 【问题描述】:

我正在使用 spring mvc + security 构建一个简单的 Web 应用程序,但目前存在登录问题。如果我想保护 /** (基本上一切),我无法从 spring 安全性中排除登录页面。这是我的配置的样子:

spring.security.xml

    <http pattern="/login" security="none"/>
    <http pattern="/view_register.htm" security="none"/>
    <http>
        <intercept-url pattern="/**" access="ROLE_USER" />
        <form-login login-page="/login" default-target-url="/game" authentication-failure-url="/failedlogin" />
        <logout logout-success-url="/login" />
</http>

登录控制器

@Controller
public class LoginLogoutController 

  @RequestMapping(value="/login", method = RequestMethod.GET)
  public String login(ModelMap model) 

    return "login";
  

  @RequestMapping(value="/failedlogin", method = RequestMethod.GET)
  public String loginerror(ModelMap model) 

    model.addAttribute("error", "true");
    return "login";
  


login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Login Page</title>
<style>
.errorblock 
    color: #ff0000;
    background-color: #ffEEEE;
    border: 3px solid #ff0000;
    padding: 8px;
    margin: 16px;

</style>
</head>
<body onload='document.f.j_username.focus();'>
    <h3>Login with Username and Password (Custom Page)</h3>

    <c:if test="$not empty error">
        <div class="errorblock">
            Your login attempt was not successful, try again.<br /> Caused :
            $sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message
        </div>
    </c:if>

    <form name='f' action="<c:url value='j_spring_security_check' />"
        method='POST'>

        <table>
            <tr>
                <td>User:</td>
                <td><input type='text' name='j_username' value=''>
                </td>
            </tr>
            <tr>
                <td>Password:</td>
                <td><input type='password' name='j_password' />
                </td>
            </tr>
            <tr>
                <td colspan='2'><input name="submit" type="submit"
                    value="submit" />
                </td>
            </tr>
            <tr>
                <td>Don't have an account yet.</td>
                <td> <a href="<c:url value="view_register.htm" />" > Register here</a>
                </td>
            </tr>
        </table>

    </form>
</body>
</html>

我想保护整个应用程序并排除登录和注册页面。使用我当前的配置,整个安全性表现得非常奇怪。如果我输入错误的凭据,

 @RequestMapping(value="/login", method = RequestMethod.GET)
  public String login(ModelMap model) 

被调用,另一方面,如果我输入正确的用户名/通过,则调用登录失败的控制器方法。

发现如果我修改了

 <intercept-url pattern="/**" access="ROLE_USER" />

<intercept-url pattern="/game*" access="ROLE_USER" />

并删除

<http pattern="/login" security="none"/>

一切都按预期工作。它非常奇怪,无法真正弄清楚为什么会这样。

编辑

刚刚创建了我的示例项目(maven)的一个小版本并上传到: fileswap。 任何帮助或建议都会非常酷,因为我仍然很困惑。

【问题讨论】:

【参考方案1】:

尝试插入这些行:

<intercept-url pattern="/login/**" access="ROLE_ANONYMOUS,ROLE_USER" />
<intercept-url pattern="/failedlogin/**" access="ROLE_ANONYMOUS,ROLE_USER" />
<intercept-url pattern="/view_register/**" access="ROLE_ANONYMOUS,ROLE_USER" />

&lt;http&gt; 之后,并在&lt;http&gt; 中添加auto-config="true"

<http auto-config="true">

    <intercept-url pattern="/login/**" access="ROLE_ANONYMOUS,ROLE_USER" />
    <intercept-url pattern="/failedlogin/**" access="ROLE_ANONYMOUS,ROLE_USER" />
    <intercept-url pattern="/view_register/**" access="ROLE_ANONYMOUS,ROLE_USER" />

    <intercept-url pattern="/**" access="ROLE_USER" />

    <form-login login-page="/login" default-target-url="/game" authentication-failure-url="/failedlogin" />
    <logout logout-success-url="/login" />
</http>

并删除:

<http pattern="/login" security="none"/>

我不知道这条线是干什么用的,但没有它它应该可以工作。

请参阅Spring Security Reference 了解有关匿名身份验证 的详细信息(要了解的重要一点是,如果匿名用户可以访问页面,并不意味着经过身份验证的用户也可以访问该页面)。

BWT,ROLE_ANONYMOUS 是一个内置角色,但 ROLE_USER 不是,正如 here 所解释的那样。您需要确保将ROLE_USER 分配给用户。

This answer 解释了为什么模式应该以/** 结尾。

【讨论】:

刚刚尝试过并且运行良好!谢谢你!我只会阅读您建议的文章/链接尝试几件事并回复您。谢谢,您为我节省了很多时间。【参考方案2】:

尝试使用允许匿名访问这些 url 的配置:

<http>
        <intercept-url pattern="/**" access="ROLE_USER" />
        <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/view_register.htm" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <form-login login-page="/login" default-target-url="/game" authentication-failure-url="/failedlogin" />
        <logout logout-success-url="/login" />
</http>

当您指定以下内容时:

<intercept-url pattern="/game*" access="ROLE_USER" />

只有像 ~/game* 这样的 URL 会受到保护,而其他所有 URL 都不受保护。

【讨论】:

感谢您的快速回复!刚刚尝试了您的解决方案(稍作修改 - 只是将 /** 移到了拦截 URL 链的底部),但仍然是同样的问题。点击 localhost:8080/webappName 后,我被重定向到 login.jsp,这很酷。即使我没有输入任何用户名或通过只是点击提交处理 /login 的方法被调用,我只是被重定向到同一个 jsp 而没有任何错误。当然,如果凭据良好,则会显示错误:您的登录尝试不成功,请重试。原因:有趣且令人沮丧。 "当您指定以下内容时: 只有像 ~/game* 这样的 URL 会受到保护,而所有其他 URL 都不受保护。 "是的,我知道,但如果我只有 /game*,login.jsp 的行为正确。如果凭据错误,则会显示错误消息,如果我输入正确的密码和用户名,我可以点击 /game。但是使用 /** 它的行为正好相反。尝试了弹簧安全配置的几种语法变体,但仍然是同样的问题。但是,无论如何,谢谢你的回答。 @shippi,你能把 * 添加到用于登录的拦截 url 模式中,然后像 @sasankad - 还是一样 :( @shippi,然后试试这个

以上是关于Spring mvc / security:从spring security中排除登录页面的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring MVC & Security、Jasig CAS 和 JSP 视图在 Spring Boot 2 中配置 UTF-8?

Spring MVC + Hibernate 4 + Spring Security

Spring Security + Angular JS + Spring MVC Rest

将 Spring MVC Spring Security 与 Undertow Web 容器集成

spring (data, mvc, security) 依赖项:IncompatibleClassChangeError

Spring Security + MVC:相同的@RequestMapping,不同的@Secured