Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用CSRF的Playframework:“使用;会话“中未找到CSRF令牌”;?_Playframework_Csrf_Playframework 2.3 - Fatal编程技术网

使用CSRF的Playframework:“使用;会话“中未找到CSRF令牌”;?

使用CSRF的Playframework:“使用;会话“中未找到CSRF令牌”;?,playframework,csrf,playframework-2.3,Playframework,Csrf,Playframework 2.3,我正在使用Playframework及其内置的CSRF过滤器和Security.Authenticator系统制作一个简单的身份验证系统,但我面临一个问题: 当用户填写登录名/密码并提交enter时,我出现以下错误: 会话中找不到CSRF令牌 我检查了我的表格,CSRF令牌确实存在并正确放置(在标签内) 这是我的路线: GET /login controllers.Authentication.login POST /login

我正在使用Playframework及其内置的CSRF过滤器和Security.Authenticator系统制作一个简单的身份验证系统,但我面临一个问题:

当用户填写登录名/密码并提交enter时,我出现以下错误:

会话中找不到CSRF令牌

我检查了我的表格,CSRF令牌确实存在并正确放置(在标签内)

这是我的
路线

GET     /login                      controllers.Authentication.login
POST    /login                      controllers.Authentication.authenticate
和我的
Authentication.java
类:

@play.filters.csrf.AddCSRFToken
public static Result login() {
    if (Session.getAccount() != null) {
        return redirect(controllers.routes.Instances.list());
    }

    LoginForm loginForm = new LoginForm();
    if (ctx().session().containsKey("email")) {
        loginForm.setEmail(ctx().session().get("email"));
    }

    if (request().queryString().containsKey("disconnected")) {
        flash("warning", Messages.get("secure.logout")); // TODO : Warning flash message
    }

    Form<LoginForm> form = Form.form(LoginForm.class).fill(loginForm);
    return ok(views.html.login.render(form));
}

@play.filters.csrf.AddCSRFToken
@play.filters.csrf.RequireCSRFCheck
public static Result authenticate() {
    Form<LoginForm> form = Form.form(LoginForm.class).bindFromRequest();
    if (form.hasErrors()) {
        return badRequest(views.html.login.render(form));
    }

    LoginForm login = form.get();
    Account account = Account.findByEmail(login.getEmail());

    if (account == null || !account.checkPassword(login.getPassword())) {
        form.reject("email", "secure.invalid.login");
        return badRequest(views.html.login.render(form));
    }

    String next = null;
    if (ctx().session().containsKey("next")) {
        next = ctx().session().get("next");
        if ("".equals(next)) {
            next = null;
        }
    }

    session().clear();
    session("email", login.getEmail());

    if (next != null) {
        return redirect(next);
    } else {
        return redirect(controllers.routes.Instances.list());
    }
}
这是我的表格(表明令牌的位置正确):


@定义(表单(“电子邮件”){element=>
电邮:
@element.errors.map{error=>@play.i18n.Messages.get(error.message)}
}
@定义(表单(“密码”){element=>
密码:
@element.errors.map{error=>@play.i18n.Messages.get(error.message)}
}
@helper.CSRF.formField
更新1:根据@rhj建议,我删除了所有
@addCSRFToken
@requireCSRFToken
,并定义了一个全局CSRF令牌。现在我得到了这个错误:

在表单正文中找到无效标记

但是正如您在HTML表单中所看到的,令牌被放置在表单中,并且应该被标识

更新2:最让我困扰的是,这个问题只发生在登录页面,而不是其他地方!是否有要首先启用的会话?我想不是,但也许

更新3:更奇怪的是,我刚刚发现,如果我更改
csrf.token.name
的值并重新加载页面,它就会工作。然后,如果我注销,打开一个新页面并再次尝试登录,它将失败,并在表单正文中找到消息
无效标记。如果我再次更改
csrf.token.name
的值并再次执行,它将再次工作

更新4:我缩小了问题的范围。我还使用play.mvc.Security.Authenticator,似乎只有当我在
重定向()后显示页面时,令牌验证才会失败。如果直接进入登录页面,则不会显示错误消息


最终更新:我终于发现了问题,我没有怀疑是在另一个类中,该类被调用并清除了会话,使得令牌无用

在Global.java中添加以下行

@Override
public <T extends EssentialFilter> Class<T>[] filters() {
    return new Class[]{CSRFFilter.class};
}

希望这将对您有所帮助

最后,问题出现在我的代码的另一部分,该部分在
login()
方法中清理会话,删除csrf令牌…

错误消息表明Play在您的cookie中找不到令牌。游戏尚未达到在你的状态下寻找代币的阶段。你看到你的饼干里有代币吗?您是否使用任何
csrf.xxx
配置属性来配置csrf过滤器?如果是这样的话,如果您恢复到默认配置会发生什么?是的,看起来确实有效。我更新了问题的信息,以反映我在.conf文件中使用的属性。最后,不,即使删除了CSRF过滤器的所有配置,有时也会出现相同的错误:/抱歉这么直截了当地问,但我面临着类似的问题,我想知道您是否有一个完整项目的github repo。我正在“尝试”学习游戏!但进展很慢。不幸的是,没有,关于游戏的唯一存储库就是这个。不确定它是否会帮助您:/I我尝试设置CSRF全局,但不幸的是,它根本没有改变。我仍然有以下错误:
在标题中找不到CSRF令牌
,或者,我有时也收到这样的消息:
在表单正文中找到无效令牌
。不明白为什么会这样!我终于找到了问题,它位于代码的另一部分,但由于您是唯一的答案,赏金将被销毁,我将它交给您;)
<form action="@controllers.routes.Authentication.authenticate" method="post" class="form-vertical" role="form">
    <fieldset>
        @defining(form("email")) { element =>
        <div class="form-group fade-in two@if(element.hasErrors){ has-error}">
            <label class="control-label" for="login-form-@element.name">Email:</label>
            <input type="email" name="@element.name" id="login-form-@element.name" class="form-control" value="@element.value" placeholder="Enter your email" required />
            @element.errors.map { error => <span class="help-block">@play.i18n.Messages.get(error.message)</span>}
        </div>}
        @defining(form("password")) { element =>
        <div class="form-group fade-in three@if(element.hasErrors){ has-error}">
            <label class="control-label" for="login-form-@element.name">Password:</label>
            <input type="password" name="@element.name" id="login-form-@element.name" class="form-control" value="@element.value" placeholder="Enter your password" required />
            @element.errors.map { error => <span class="help-block">@play.i18n.Messages.get(error.message)</span>}
        </div>}
        <div class="form-group actions fade-in four">
            <div class="text-right">
                <input type="submit" name="save" value="Sign me in" class="btn btn-primary" />
                @helper.CSRF.formField
            </div>
        </div>
    </fieldset>
</form>
@Override
public <T extends EssentialFilter> Class<T>[] filters() {
    return new Class[]{CSRFFilter.class};
}
import play.api.mvc.EssentialFilter;
import play.filters.csrf.CSRFFilter;