密码更新时出现未授权错误 Devise

4
我正在开发一个Rails API,并使用devise_token_auth进行身份验证。当我尝试使用put请求更新密码时,访问/auth/password会响应错误401,即未经授权。我的服务器日志显示了以下内容:

开始PUT“/auth/password”处理由DeviseTokenAuth :: PasswordsController#update作为HTML的参数: {"password" =>“[FILTERED]”,“password_confirmation”=>“[FILTERED]”} 无法验证CSRF令牌的真实性已完成401未经授权

routes.rb

mount_devise_token_auth_for 'User', at: 'auth' ,:controllers => { :omniauth_callbacks => 'omniauth'  }

视图.html(AngularJS)

<div class="container">
    <div class="row">

    <div class="row">
       <div class="col-xs-6 col-xs-offset-3 que">
           <img src="./uploads/img/web-logo.png" class="img-responsive" alt="Logo">
       </div>
    </div>
        <div class="col-xs-12 reset-pas">
            <form  name="update_pass" ng-submit="updatePassword_controller()" role="form" class="lost_reset_password">
                <p class="error_msg" ng-show="update_pass.password_confirmation.$error.passwordVerify"> 
                    Passwords are not equal!
                </p>
            <label>New password</label>
            <input type="password" name="password"  ng-minlength="8"  ng-model="updatePasswordForm.password" required="required" class="form-control">
            <span>Minimum 8 Charachters</span>
    <br>
            <label>Re-enter new password</label>

            <input type="password" name="password_confirmation"  ng-minlength="8"  ng-model="updatePasswordForm.password_confirmation" required="required" class="form-control"  password-verify="updatePasswordForm.password" >
                <button type="submit" class="btn btn-default" id="reset-submit">Save</button>
            </form>
        </div>
    </div>
</div>

controller.js

$scope.updatePassword_controller = function() {

  $auth.updatePassword($scope.updatePasswordForm)
    .then(function(resp) {
      console.log(resp)
      $location.path('/')
    })
    .catch(function(resp) {
      console.log(resp)
    });
};

更新 注意 我只遇到了密码更新的问题

更新

我安装了gem 'angular_rails_csrf'现在只会给出授权错误而不是csrf攻击错误


你是怎么发送请求的?你的请求中缺少CSRF(authenticity_token)信息。 - zekus
@zekus,你好,请问我该如何添加它? - Mani
这个问题在这里被问到了:https://dev59.com/p2Uq5IYBdhLWcg3wKtRL#15761835,同时也可以参考这篇文章:http://solidfoundationwebdev.com/blog/posts/how-to-set-csrf-with-angularjs-and-rails。我想这应该能解决问题。 - zekus
@zekus 不好意思,问题还是一样的。 - Mani
2个回答

1
使用Rails的form_tagform_for助手。它们将添加一个隐藏字段用于XCSRF令牌。
<div class="container">
    <div class="row">

    <div class="row">
       <div class="col-xs-6 col-xs-offset-3 que">
           <img src="./uploads/img/web-logo.png" class="img-responsive" alt="Logo">
       </div>
    </div>
        <div class="col-xs-12 reset-pas">
            <%= form_tag "#", { "ng-submit" => "updatePassword_controller()", "role" => "form", "class" => "lost_reset_password"} do %>
                <p class="error_msg" ng-show="update_pass.password_confirmation.$error.passwordVerify"> 
                    Passwords are not equal!
                </p>
            <label>New password</label>
            <input type="password" name="password"  ng-minlength="8"  ng-model="updatePasswordForm.password" required="required" class="form-control">
            <span>Minimum 8 Charachters</span>
    <br>
            <label>Re-enter new password</label>

            <input type="password" name="password_confirmation"  ng-minlength="8"  ng-model="updatePasswordForm.password_confirmation" required="required" class="form-control"  password-verify="updatePasswordForm.password" >
                <button type="submit" class="btn btn-default" id="reset-submit">Save</button>
            </form>
        </div>
    </div>
</div>

我的错,模板在AngularJS的HTML中。 - Mani
你的意思是你正在使用静态HTML在Rails之外部署你的Angular应用程序?如果是这样,你需要禁用Rails的CSRF保护,因为它依赖于服务器端渲染。 - max
如果您正在使用基于令牌的身份验证,可以通过删除会话中间件来实现此目的。 - max
最初它正在更新密码,但我不知道为什么它停止了。此外,我不知道如何删除会话中间件。 - Mani

1

我只是在 applicationcontroller.rb 中设置了一个条件,如下所示,它就奏效了。主要思路就是简单地覆盖 Devise 的功能。

        if params[:controller] == "devise_token_auth/passwords" && params[:action] == "update"

              uri               = URI.parse(request.headers.env['HTTP_REFERER'])
              query_params      = CGI.parse(uri.query)
              email             = query_params['uid'].first
              user              = User.find_by_email(email)
              user.password     = params[:password]
              user.password_confirmation = params[:password_confirmation]

              if user.save
                    render json: {message: 'Password Updated successfully', status: 200}                        
              else
                    render json: {message: 'Password Could not changed , Please contact to support Team', status: 401}
              end
        end

虽然这不是正确的解决方案,但我想不到其他方法。请原谅我。在其中,我们正在从URL获取电子邮件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接