curl - 使用 cURL 使用用户名和密码登录 Gitlab

标签 curl gitlab csrf

为了在 Docker 中针对 Gitlab 实例测试命令行工具,我想使用用户名和密码登录 Gitlab,并获取创建的 session 以验证我的 API 请求。

因此,我执行以下操作:

  • 使用 curl -i http://localhost:8080/users/sign_in -s
  • curl 用户登录页面
  • 从标题
  • 中获取 _gitlab_session
  • 从登录表单
  • 中获取 authenticity_token
  • 使用
  • 发送第二个 curl 请求
    
    curl 'http://localhost:8080/users/sign_in' \
      -H "_gitlab_session=${cookie}" \
      -H 'Origin: http://localhost:8080' \
      -H 'Content-Type: application/x-www-form-urlencoded' \
      -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' \
      -H 'Referer: http://localhost:8080/users/sign_in' \
      -H 'Connection: keep-alive' \
      --data-urlencode "authenticity_token=${token}" \
      --data-urlencode "user[login]=root" \
      --data-urlencode "user[password]=12341234" \
      --data-urlencode "user[remember_me]=0"
    

    但是我得到了一个有效的用户登录而不是有效的用户登录
    422 - The change you requested was rejected.
    

    在日志文件中,我看到
    ==> gitlab-rails/production.log <==
    Started POST "/users/sign_in" for 172.17.0.1 at 2017-12-23 00:22:16 +0000
    Processing by SessionsController#create as HTML
    Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"login"=>"root", "password"=>"[FILTERED]", "remember_me"=>"0"}}
    Can't verify CSRF token authenticity
    Completed 422 Unprocessable Entity in 125ms (ActiveRecord: 7.8ms)
    
    ==> gitlab-rails/production_json.log <==
    {"method":"POST","path":"/users/sign_in","format":"html","controller":"SessionsController",  
    "action":"create","status":422,"error":" 
    ActionController::InvalidAuthenticityToken:ActionController::InvalidAuthenticityToken",
    "duration":126.29,"view":0.0,"db":7.78,"time":"2017-12-23T00:22:16.039Z",
    "params":{"authenticity_token":"[FILTERED]","user":{"login":"root","password":"
    [FILTERED]","remember_me":"0"}},"remote_ip":"172.17.0.1",
    "user_id":1,"username":"root"}
    
    ==> gitlab-rails/production.log <==
    
    ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
      lib/gitlab/middleware/multipart.rb:93:in `call'
      lib/gitlab/request_profiler/middleware.rb:14:in `call'
      lib/gitlab/middleware/go.rb:18:in `call'
      lib/gitlab/etag_caching/middleware.rb:11:in `call'
      lib/gitlab/middleware/read_only.rb:31:in `call'
      lib/gitlab/request_context.rb:18:in `call'
      lib/gitlab/metrics/requests_rack_middleware.rb:27:in `call'
    

    我假设我忘记在第二个请求中传递必要的成分 - 但我不知道是哪一个。

    最佳答案

    通过其他答案和评论的一些有用提示,我终于想出了这个解决方案:

    gitlab_host="http://localhost:8080"
    gitlab_user="root"
    gitlab_password="12341234"
    
    # curl for the login page to get a session cookie and the sources with the auth tokens
    body_header=$(curl -c cookies.txt -i "${gitlab_host}/users/sign_in" -s)
    
    # grep the auth token for the user login for
    #   not sure whether another token on the page will work, too - there are 3 of them
    csrf_token=$(echo $body_header | perl -ne 'print "$1\n" if /new_user.*?authenticity_token"[[:blank:]]value="(.+?)"/' | sed -n 1p)
    
    # send login credentials with curl, using cookies and token from previous request
    curl -b cookies.txt -c cookies.txt -i "${gitlab_host}/users/sign_in" \
        --data "user[login]=${gitlab_user}&user[password]=${gitlab_password}" \
        --data-urlencode "authenticity_token=${csrf_token}"
    
    # send curl GET request to personal access token page to get auth token
    body_header=$(curl -H 'user-agent: curl' -b cookies.txt -i "${gitlab_host}/profile/personal_access_tokens" -s)
    csrf_token=$(echo $body_header | perl -ne 'print "$1\n" if /authenticity_token"[[:blank:]]value="(.+?)"/' | sed -n 1p)
    
    # curl POST request to send the "generate personal access token form"
    # the response will be a redirect, so we have to follow using `-L`
    body_header=$(curl -L -b cookies.txt "${gitlab_host}/profile/personal_access_tokens" \
        --data-urlencode "authenticity_token=${csrf_token}" \
        --data 'personal_access_token[name]=golab-generated&personal_access_token[expires_at]=&personal_access_token[scopes][]=api')
    
    # Scrape the personal access token from the response HTML
    personal_access_token=$(echo $body_header | perl -ne 'print "$1\n" if /created-personal-access-token"[[:blank:]]value="(.+?)"/' | sed -n 1p)
    
    根据 GitLab API documentation,您现在可以使用 session cookie 来验证 API 请求:
    curl --header "Private-Token: ${personal_access_token}" https://gitlab.example.com/api/v4/projects
    
    一些提示:
  • 我第一次混淆了 curl -c file(它从头文件中读取 cookie 并将它们写入文件)与 curl -b file(它使用文件中的 cookie 并将它们与请求一起发送)
  • 不幸的是,我没有找到与 sed 一起使用的正则表达式,所以我必须在这里使用 perl
  • 在 Chrome 中使用开发者控制台并将 POST 请求复制为 curl 命令非常有帮助:https://www.alexkras.com/copy-any-api-call-as-curl-request-with-chrome-developer-tools/
  • 关于curl - 使用 cURL 使用用户名和密码登录 Gitlab,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47948887/

    相关文章:

    c - 在 C 中发送 RCPT TO?

    git - 使用 HTTP 请求检查 git repo 是否公开

    asp.net - 使用 MVC2 的 AJAX 请求中的 CSRF 保护

    javascript - 为什么要将 CSRF token 放入 JWT token 中?

    http - 为什么同源策略不阻止 POST 请求?

    C++ libCurl : Post callback function to send more than one byte

    python - 如何使用 curl 或请求捕获重定向

    ubuntu - Gitlab导出: Could not locate Gemfile or .包/目录

    rest - HTTP POST 的 cURL 请求在语法上不正确

    java - 使用 JGit 连接到 GitLab 时出错