如何在Flask中登录后重定向到受保护的URL?

huangapple go评论97阅读模式
英文:

How can I redirect to a protected URL after login in Flask?

问题

我正在开发一个微服务的Web项目。在后端,我有一个负责检查用户凭据并返回有效JWT的登录服务。我还有另一个名为Views的服务,负责提供UI并向其他服务发送请求。从客户端发出的每个请求首先访问Views服务,然后将请求传递给适当的服务。

在Views服务中向"/login"路由发送AJAX请求的代码:

function login(){
   $('#login-form').submit(function(){
      $.ajax({
          url: $('#login-form').attr('action'),
          type: 'POST',
          data : $('#login-form').serialize(),
          success: function(res, status, xhr){
             window.localStorage.setItem("x-access-token", xhr.getResponseHeader("x-access-token"));
             $.ajax({
                url: "/user/profile",
                type: "GET",
                headers: {
                  "x-access-token": window.localStorage.getItem("x-access-token")
                },
                success: function () {
                   window.location.replace("/user/profile")
                },
                error: function (response) {
                   alert("Error in GET: " + response)
                }
              });
          }, error: function (response) {
               alert(response)
          }
       })
    });
}

将请求传递给Login服务的代码:

@views_blueprint.route("/login", methods=["POST"])
def user_login():
    email = request.form["email"]
    password = request.form["password"]

    r = requests.post("http://login:5000/login", json={"data": {"email": email, "password": password}})

    try:
        login_resp = r.json()
        if login_resp["status"] == 201:
            @after_this_request
            def send_token(response):
                response.headers["x-access-token"] = login_resp["token"]
                return response
            return json.dumps(login_resp)
        else:
            return render_template("/error/error.html", error_code=login_resp["status"], error_message=login_resp["message"])
    except Exception as e:
        return render_template("/error/error.html", error_code=500, error_message=f"Error occurred. {e}")

我可以成功发送登录请求并获取令牌并存储在localStorage中。我遇到的问题是,在登录后,我需要将用户重定向到受保护的路由,并且我需要将JWT添加到请求头中。我尝试在function login()中使用AJAX GET请求来实现这一点。然而,GET请求从未发送,而是Flask渲染了user_login()函数中返回的JSON对象。

我该如何解决这个问题?如果我正在行不通的方式上做事,是否有人能指点我正确的方向?

英文:

I am developing a web project with microservices. In the backend, I have a Login service which is responsible for checking the user credentials and returning a valid JWT. I have another service called Views which is responsible for serving the UI and sending requests to other services. Every request coming from the client first visits Views service and then the requests are delivered to proper services.

The code for sending ajax request to "/login" route in the Views service:

function login(){
   $('#login-form').submit(function(){
      $.ajax({
          url: $('#login-form').attr('action'),
          type: 'POST',
          data : $('#login-form').serialize(),
          success: function(res, status, xhr){
             window.localStorage.setItem("x-access-token", xhr.getResponseHeader("x-access-token"));
             $.ajax({
                url: "/user/profile",
                type: "GET",
                headers: {
                  "x-access-token": window.localStorage.getItem("x-access-token")
                },
                success: function () {
                   window.location.replace("/user/profile")
                },
                error: function (response) {
                   alert("Error in GET: " + response)
                }
              });
          }, error: function (response) {
               alert(response)
          }
       })
    });
}

Code that delivers the request to Login service:

@views_blueprint.route("/login", methods=["POST"])
def user_login():
    email = request.form["email"]
    password = request.form["password"]

    r = requests.post("http://login:5000/login", json={"data": {"email": email, "password": password}})

    try:
        login_resp = r.json()
        if login_resp["status"] == 201:
            @after_this_request
            def send_token(response):
                response.headers["x-access-token"] = login_resp["token"]
                return response
            return json.dumps(login_resp)
        else:
            return render_template("/error/error.html", error_code=login_resp["status"], error_message=login_resp["message"])
    except Exception as e:
        return render_template("/error/error.html", error_code=500, error_message=f"Error occurred. {e}")

I can successfully send login request and get token back and store it in the localStorage. Issue I am having is, after logging in I need to redirect the user to a protected route and I need to add the JWT to the request headers. I tried to achieve this with an ajax GET request in the function login(). However, the GET request is never sent instead Flask renders the JSON object returned in the user_login() function.

How can I overcome this issue? If what I am doing is the wrong way, could anyone point me in the right direction?

答案1

得分: 1

我刚刚处理了JWT,所以我看到你了,只是想给你一个建议,希望能帮到你。

如果我理解正确的话,你的问题是在成功登录后,你想要将用户和有效令牌转发到你的应用程序中标记为jwt_required的实际页面?

我总是这样做:

# 现在我们在登录函数中,数据有效:
access_token = create_access_token(identity=username)
refresh_token = create_refresh_token(identity=username)
# 现在让我们创建一个带有重定向的响应对象:
resp_obj = make_response(redirect(url_for('func_with_jwt_required'), 302))
# 所以现在只有响应对象需要令牌,然后你可以返回它
set_access_cookies(resp_obj, access_token)
set_refresh_cookies(resp_obj, refresh_token)
return resp_obj

如果有帮助,请给我写信。

如果没有,请解释一下我可能没有正确理解你的方法的地方(因为我的方法在我的应用程序上运行正常),然后我会仔细查看你的问题,帮助你解决方法。

祝你有一个愉快的一天。

英文:

<br>
I have just deal with JWT myself, so I saw you and I just wanted to give you a tip, I hope it will help you.<br>
Your problem, if I've read that correctly, is that after a successful login you want to forward the user and valid token to the actual page in your app that is marked with jwt_required?<br>
I always do it like this:

# we are now in the login func and data is valid:
access_token = create_access_token(identity=username)
refresh_token = create_refresh_token(identity=username)
# now lets make a response object with a redirect:
resp_obj = make_response(redirect(url_for(&#39;func_with_jwt_required&#39;), 302))
# so now only the response object needs the token&#180;s and you can return it
set_access_cookies(resp_obj, access_token)
set_refresh_cookies(resp_obj, refresh_token)
return resp_obj

> Please write to me if it helped you.
<br>
If not, please explain to me what I did not understand correctly about your method (because my method works on my applications without any problems), then I'll take a closer look at your problem and help you with your approach.

Nice day

huangapple
  • 本文由 发表于 2020年1月6日 21:05:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/59612659.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定