【问题标题】:How to combine token Authenication and CRSF?如何结合token Authentication和CSRF?
【发布时间】:2017-02-27 10:10:26
【问题描述】:

我正在开发一个包含以下内容的网络应用程序

  • Rest Web 服务(春季 4)| JWT令牌认证
  • 网页(login.xhtml、index.xhtml)(JSF、primeface)| crsf

我现在面临的问题很奇怪。

如果我的 spring 安全性被启用,任何对 REST Web 服务的访问都需要在被授予访问权限之前进行身份验证。我正在使用 JWT 令牌身份验证进行登录。但是我的网页在我登录后会失败。即我的登录成功,但此后的任何操作都会导致invalid crsf token or null request error.

如果我的 Spring Security 被禁用,我的其余服务不需要经过身份验证即可访问 Web 服务,但我的网页可以正常工作。

如何将这两种解决方案集成在一起?

我的所有网页都已包含以下内容:

<input type="hidden" name="${_csrf.parameterName}"
                value="${_csrf.token}" />

ApplicationContext-Security.xml:

<http pattern="/auth/login" security="none" />
    <http pattern="/login.xhtml" security="none" />
    <http pattern="/index.xhtml" security="none" />
    <http pattern="/javax.faces.resource/**" security="none" />
    <http pattern="/RES_NOT_FOUND" security="none" />
    <http pattern="/img/**" security="none" />

    <sec:http auto-config="false" create-session="stateless" entry-point-ref="customEntryPoint" use-expressions="true">
        <intercept-url pattern="/admin/**"          access="hasRole('ADMIN') or hasRole('HQ')" />
        <intercept-url pattern="/audit/**"          access="hasRole('ADMIN')" />
        <intercept-url pattern="/request/**"        access="hasRole('ADMIN') or hasRole('HQ')" />
        <intercept-url pattern="/reporting/**"      access="hasRole('ADMIN') or hasRole('HQ')" />

        <sec:custom-filter ref="customAuthenticationFilter"
            before="PRE_AUTH_FILTER" />

<!--        <sec:csrf disabled="true" /> -->
    </sec:http>

如您所见,我包含了&lt;http pattern="/index.xhtml" security="none" /&gt;,这样我就可以允许我的 index.xhtml 中的功能起作用。但是现在我可以直接访问 index.xhtml 了。

有人可以建议如何解决这个问题吗?

===== 已编辑。更多信息 =====

补充一下,这是我的登录页面和控制器。

login.xhtml:

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">

<h:head>
    <title>BTS Upload</title>
    <h:outputStylesheet library="css" name="bootstrap.min.css" />
    <h:outputScript library="js" name="jquery-1.11.1.min.js" />
    <h:outputScript library="js" name="bootstrap.min.js" />
</h:head>

<!-- Css here -->

<h:body>
    <font color="red"> <h:outputLabel
            value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
    </font>

    <div class="container">
        <div class="row">
            <div class="col-sm-6 col-md-4 col-md-offset-4">
                <h1 class="text-center login-title">Sign in</h1>
                <div class="account-wall">

                    <h:graphicImage class="profile-img" library="images"
                        name="photo.png" />

                    <h:form class="form-signin">
                        <h:outputLabel value="Enter UserName:" />

                        <h:inputText id="username" value="#{loginAction.username}"
                            required="true" requiredMessage="Please enter your username"
                            autofocus="true" class="form-control"></h:inputText>

                        <h:message for="username" id="msg"
                            errorStyle="color:red; display:block" />

                        <br />
                        <h:outputLabel value="Enter Password:" />
                        <h:inputSecret id="password" value="#{loginAction.pwd}"
                            required="true" requiredMessage="Please enter your password"
                            class="form-control"></h:inputSecret>

                        <h:message for="password" id="msg1"
                            errorStyle="color:red; display:block" />

                        <br />
                        <br />

                        <h:commandButton class="btn btn-lg btn-primary btn-block"
                            action="#{loginAction.login}"
                            value="Login"></h:commandButton>

                        <input type="hidden" name="${_csrf.parameterName}"
                            value="${_csrf.token}" />

                    </h:form>
                </div>

            </div>
        </div>
    </div>
</h:body>
</html>

控制器:

@ManagedBean(name="loginAction")
@SessionScoped
public class LoginAction extends BaseAction implements Serializable
{
    private static final long serialVersionUID = 1094801825228386363L;

    private String pwd;
    private String msg;
    private String username;

    @ManagedProperty("#{accessControlService}")
    private AccessControlService accessControlService;

    public String getPwd()
    {
        return pwd;
    }

    public void setPwd(String pwd)
    {
        this.pwd = pwd;
    }

    public String getMsg()
    {
        return msg;
    }

    public void setMsg(String msg)
    {
        this.msg = msg;
    }

    public String getUsername()
    {
        return username;
    }

    public void setUsername(String user)
    {
        this.username = user;
    }

    //validate login and redirect to the specified website.
    public String login()
    {

        System.out.println();
        System.out.println("Call Log in");

        if (username.equals("") || pwd.equals(""))
        {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,
                    "Incorrect Username and Password", "Please enter correct username and Password"));
            return "login";
        }

        boolean valid = false;
        String token = "";

        try
        {
            token = accessControlService.isAuthorizedUser(username, pwd, PropertiesUtil.LoginType.WEB_BTS.ordinal(), this.getRequest());
        }
        catch (Exception e)
        {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,
                    "Error", e.getLocalizedMessage()));
        }

        if(token.contains(PropertiesUtil.TOKEN_HEADER))
        {
            valid = true;
        }

        if (valid)
        {
            HttpSession session = this.getSession();
            session.setAttribute("username", username);
            session.setAttribute("token", token);

            return "admin";
        }
        else
        {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,
                    "Incorrect Username and Password", "Please enter correct username and Password"));
            return "login";
        }
    }

    // logout event, invalidate session
    public String logout()
    {
        System.out.println("**********************************************************");
        try
        {
            accessControlService.logout(getUsername(), PropertiesUtil.LoginType.WEB_BTS.ordinal(), getRequest());
            HttpSession session = this.getSession();
            session.invalidate();
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return "login";
    }

    public AccessControlService getAccessControlService()
    {
        return accessControlService;
    }

    public void setAccessControlService(AccessControlService accessControlService)
    {
        this.accessControlService = accessControlService;
    }
}

【问题讨论】:

    标签: spring rest jsf


    【解决方案1】:

    首先你必须确保你有 spring security 4 兼容的 *-security.xml 和 *-servlet.xml look at this

    从您发布的 security.xml 的一部分中,我可以看到您没有 form-login 标记。应该是这样的

    <security:form-login default-target-url="/index"
                             login-page="/login"
                             username-parameter="j_username"
                             password-parameter="j_password"
                             login-processing-url="/j_spring_security_check"
                             authentication-failure-url="/login?login_error=1"/>
    

    你的登录jsp需要有动作j_spring_security_check来触发过滤链:

    <form action="<c:url value="/j_spring_security_check"/>" method="POST"> ... 
    

    你不需要 csrf 隐藏输入,因为从 spring 4 开始,spring 会自动将它注入到请求标头和参数中(如果你不禁用它)

    【讨论】:

    • 我已经用我的登录页面和控制器更新了我的帖子。在此之前我尝试了表单登录,但仍然无法正常工作,因为我使用的是 primeface。我实际上有自己的身份验证课程。如何修改上面的xml文件?
    猜你喜欢
    • 2016-04-19
    • 2014-11-21
    • 2017-05-19
    • 2018-01-18
    • 2018-10-14
    • 2018-04-13
    • 2021-04-28
    • 1970-01-01
    • 2017-07-13
    相关资源
    最近更新 更多