大猩猩会话在客户端的CORS上不起作用。

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

Gorilla sessions not working for CORS from client

问题

我已经设置了一个Go的REST API。在登录时,我执行以下操作:

  1. session, _ := store.New(r, sessionId)
  2. session.Options.MaxAge = 12 * 3600
  3. err := session.Save(r, w)
  4. //处理错误

检查会话时,我有类似以下的代码:

  1. session, err := store.Get(r, sessionId)
  2. //处理错误
  3. if session.IsNew {
  4. http.Error(w, "未经授权的会话。", http.StatusUnauthorized)
  5. return
  6. }

如果我使用Postman发送请求,一切正常,但是当我从我的客户端发送请求时,我收到401错误。你们有没有遇到过类似的情况?存储是一个CookieStore。

我已经检查了ID,我用一个静态字符串替换了sessionId变量。Gorilla session使用Gorilla context来注册一个新的请求,当我从Postman发送请求时,context.data[r]不为空,但是从客户端发送请求时,它始终为空,即始终是一个新的会话。

https://github.com/gorilla/context/blob/master/context.go - 第33行

它在以下位置被调用:

https://github.com/gorilla/sessions/blob/master/sessions.go - 第122行

在CookieStore.Get函数中使用:

https://github.com/gorilla/sessions/blob/master/store.go - 第77行

编辑1:
对于客户端,我使用Polymer和XMLHttpRequest进行了尝试。

Polymer:

  1. <iron-ajax
  2. id="ajaxRequest"
  3. auto
  4. url="{{requestUrl}}"
  5. headers="{{requestHeaders}}"
  6. handle-as="json"
  7. on-response="onResponse"
  8. on-error="onError"
  9. content-type="application/json"
  10. >
  11. </iron-ajax>

处理函数:

  1. onResponse: function(response){
  2. console.log(response.detail.response);
  3. this.items = response.detail.response
  4. },
  5. onError: function(error){
  6. console.log(error.detail)
  7. },
  8. ready: function(){
  9. this.requestUrl = "http://localhost:8080/api/fingerprint/company/" + getCookie("companyId");
  10. this.requestHeaders = {"Set-cookie": getCookie("api_token")}
  11. }

并且cookie成功传递到后端。

XMLHttpRequest:

  1. var xmlhttp = new XMLHttpRequest();
  2. xmlhttp.onreadystatechange = function() {
  3. if (xmlhttp.readyState == XMLHttpRequest.DONE ) {
  4. if(xmlhttp.status == 200){
  5. //做一些操作
  6. }else if(xmlhttp.status == 401){
  7. page.redirect("/unauthorized")
  8. }else{
  9. page.redirect("/error")
  10. }
  11. }
  12. }
  13. xmlhttp.open("GET","http://localhost:8080/api/fingerprint/company/" + getCookie("companyId"),true);
  14. xmlhttp.setRequestHeader("Set-cookie", getCookie("api_token"));
  15. xmlhttp.send();

编辑2:
所以我尝试使用Fiddler进行调试(感谢建议),我发现从Postman发送的请求中有一个粗体条目Cookies / Login,而来自客户端的请求没有。有没有办法获取/设置这个值?在身份验证请求中,我收到了一个包含所有所需数据的set-cookie头,但是我无法在客户端获取它。我收到了Refused to get unsafe header set-cookie的错误。

英文:

I have set up a Go rest api. And on login I do this:

  1. session, _ := store.New(r, sessionId)
  2. session.Options.MaxAge = 12 * 3600
  3. err := session.Save(r, w)
  4. //treat error

and for checking the session i have smth like this:

  1. session, err := store.Get(r, sessionId)
  2. //treat error
  3. if session.IsNew {
  4. http.Error(w, &quot;Unauthorized session.&quot;, http.StatusUnauthorized)
  5. return
  6. }

If I do the requests from postman it works fine, but when I do them from my client I get 401. Has any of you experienced something like this? The store is a CookieStore.

I already checked the id's, I replaced sessionId variable with a static string. Gorilla session uses gorilla context to register a new request and when I do the request from postman context.data[r] is not null, but from the client it is always null -> always a new session.

https://github.com/gorilla/context/blob/master/context.go - line 33

it is called in

https://github.com/gorilla/sessions/blob/master/sessions.go - line 122

wich is used in the CookieStore.Get function in

https://github.com/gorilla/sessions/blob/master/store.go - line 77

EDIT 1:
For the client I use polymer and I tried xmlhttp too.
Polymer:

  1. &lt;iron-ajax
  2. id=&quot;ajaxRequest&quot;
  3. auto
  4. url=&quot;{{requestUrl}}&quot;
  5. headers=&quot;{{requestHeaders}}&quot;
  6. handle-as=&quot;json&quot;
  7. on-response=&quot;onResponse&quot;
  8. on-error=&quot;onError&quot;
  9. content-type=&quot;application/json&quot;
  10. &gt;
  11. &lt;/iron-ajax&gt;

and the handlers

  1. onResponse: function(response){
  2. console.log(response.detail.response);
  3. this.items = response.detail.response
  4. },
  5. onError: function(error){
  6. console.log(error.detail)
  7. },
  8. ready: function(){
  9. this.requestUrl = &quot;http://localhost:8080/api/fingerprint/company/&quot; + getCookie(&quot;companyId&quot;);
  10. this.requestHeaders = {&quot;Set-cookie&quot;: getCookie(&quot;api_token&quot;)}
  11. }

and the cookie successfully reaches the backend.

And xmlhttp:

  1. var xmlhttp = new XMLHttpRequest();
  2. xmlhttp.onreadystatechange = function() {
  3. if (xmlhttp.readyState == XMLHttpRequest.DONE ) {
  4. if(xmlhttp.status == 200){
  5. //do stuff
  6. }else if(xmlhttp.status == 401){
  7. page.redirect(&quot;/unauthorized&quot;)
  8. }else{
  9. page.redirect(&quot;/error&quot;)
  10. }
  11. }
  12. }
  13. xmlhttp.open(&quot;GET&quot;,&quot;http://localhost:8080/api/fingerprint/company/&quot; + getCookie(&quot;companyId&quot;),true);
  14. xmlhttp.setRequestHeader(&quot;Set-cookie&quot;, getCookie(&quot;api_token&quot;));
  15. xmlhttp.send();

EDIT 2:

So I tried debugging with fiddler(thanks for the suggestion) and i found out that the request from postman has an bold entry Cookies / Login and the request from the client does not. Any idea how to get/set that value? It is somehow automatically set in Postman. In the authentication request I get a set-cookie header that has all the data that I need but I can't get it on the client. I get Refused to get unsafe header set-cookie.

答案1

得分: 3

问题在于在客户端中,请求需要设置withCredentials = true,然后浏览器会处理一切。它从set-cookie头部获取cookie,并通过cookie头部发送cookie。所以,最终,这不是一个gorilla sessions的问题。

英文:

The problem is that in the client the requests need to have withCredentials = true and after that the browser deals with everything. It gets the cookie from the set-cookie header and it sends the cookies via the cookie header. So, after all, it was not a gorilla sessions problem.

答案2

得分: 0

如果其他人遇到了和我一样的问题,并且你想要将所有域名/通配符添加到白名单(或者有一个域名列表数组可以进行扫描),你可以像这样做。

  1. domain_raw := r.Host
  2. domain_host_parts := strings.Split(domain_raw, ".")
  3. domain := domain_host_parts[1] + "." + domain_host_parts[2]
  4. domains := getDomains() // 存储允许的域名切片
  5. has_domain := false
  6. for _, d := range domains {
  7. if d == domain {
  8. has_domain = true
  9. break
  10. }
  11. }
  12. if has_domain == false {
  13. return
  14. } else {
  15. w.Header().Add("Access-Control-Allow-Origin", "https://"+domain_raw)
  16. w.Header().Add("Access-Control-Allow-Credentials", "true")
  17. }

我喜欢Go语言。

英文:

If anyone else is having the same problem I was having and you want to whitelist all domains/wildcards (or have a list of domains in an array you can scan through), you can do something like this.

  1. domain_raw := r.Host
  2. domain_host_parts := strings.Split(domain_raw, &quot;.&quot;)
  3. domain := domain_host_parts[1] + &quot;.&quot; + domain_host_parts[2]
  4. domains := getDomains() // stores a slice of all your allowable domains
  5. has_domain := false
  6. for _, d := range domains {
  7. if d == domain {
  8. has_domain = true
  9. break
  10. }
  11. }
  12. if has_domain == false {
  13. return
  14. } else {
  15. w.Header().Add(&quot;Access-Control-Allow-Origin&quot;, &quot;https://&quot;+domain_raw)
  16. w.Header().Add(&quot;Access-Control-Allow-Credentials&quot;, &quot;true&quot;)
  17. }

I love go

huangapple
  • 本文由 发表于 2015年7月16日 16:06:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/31448642.html
匿名

发表评论

匿名网友

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

确定