我让用户登录页面.当他们成功登录时,这会将他们重定向到用户页面.然而,这并没有发生,我不确定为什么.似乎ajax调用出于某种原因(我不确定为什么)会出错.当我记录响应时,我可以看到新页面已通过响应文本.

应重定向用户的登录方法:

// this map stores the users sessions. For larger scale applications, you can use a database or cache for this purpose
var sessions = map[string]session{}

// each session contains the username of the user and the time at which it expires
type session struct {
    username string
    expiry   time.Time
}

// we'll use this method later to determine if the session has expired
func (s session) isExpired() bool {
    return s.expiry.Before(time.Now())
}

// Credentials Create a struct that models the structure of a user in the request body
type Credentials struct {
    Password string `json:"password"`
    Username string `json:"username"`
}

func login(w http.ResponseWriter, r *http.Request) {
    log.Println("login started")

    var creds Credentials
    // Get the JSON body and decode into credentials
    if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
        // If the structure of the body is wrong, return an HTTP error
        log.Println(err)
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    // Get the expected password from our in memory map
    expectedPassword, ok := "test", true

    // If a password exists for the given user
    // AND, if it is the same as the password we received, then we can move ahead
    // if NOT, then we return an "Unauthorized" status
    if !ok || expectedPassword != creds.Password {
        log.Println("bad password")
        w.WriteHeader(http.StatusUnauthorized)
        return
    }

    // Create a new random session token
    // we use the "github.com/google/uuid" library to generate UUIDs
    sessionToken := uuid.NewString()
    expiresAt := time.Now().Add(120 * time.Second)

    // Set the token in the session map, along with the session information
    sessions[sessionToken] = session{
        username: creds.Username,
        expiry:   expiresAt,
    }

    // Finally, we set the client cookie for "session_token" as the session token we just generated
    // we also set an expiry time of 120 seconds
    http.SetCookie(w, &http.Cookie{
        Name:    "session_token",
        Value:   sessionToken,
        Expires: expiresAt,
    })

    log.Println("login success")

    http.Redirect(w, r, "/users", http.StatusFound)
}

Ajax调用:

        function handleSubmit(evt) {
            evt.preventDefault();
            let form = evt.target;
            let data = new FormData(form);
            if (data.get("username") != null && data.get("username") != "") {
                $.ajax({
                    url: '/login',
                    method: 'post',
                    data: JSON.stringify(Object.fromEntries(data)),
                    dataType: 'json',
                    success: (resp) => {
                        if (resp.redirect) {
                            // resp.redirect contains the string URL to redirect to
                            window.location.redirect = resp.redirect;
                        }
                    },
                    error: (resp) => {
                        console.log("An error occurred. Please try again");
                        console.log(resp)
                    }
                });
            }
            return false
        }

Response text example

推荐答案

所以为了解决你的问题,你应该修改一下你的服务器代码

func login(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json; charset=utf-8")

    log.Println("login started")

    var creds Credentials
    // Get the JSON body and decode into credentials
    if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
        // If the structure of the body is wrong, return an HTTP error
        log.Println(err)
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    // Get the expected password from our in memory map
    expectedPassword, ok := "test", true

    // If a password exists for the given user
    // AND, if it is the same as the password we received, then we can move ahead
    // if NOT, then we return an "Unauthorized" status
    if !ok || expectedPassword != creds.Password {
        log.Println("bad password")
        w.WriteHeader(http.StatusUnauthorized)
        return
    }

    // Create a new random session token
    // we use the "github.com/google/uuid" library to generate UUIDs
    sessionToken := uuid.NewString()
    expiresAt := time.Now().Add(120 * time.Second)

    // Set the token in the session map, along with the session information
    sessions[sessionToken] = session{
        username: creds.Username,
        expiry:   expiresAt,
    }

    // Finally, we set the client cookie for "session_token" as the session token we just generated
    // we also set an expiry time of 120 seconds
    http.SetCookie(w, &http.Cookie{
        Name:    "session_token",
        Value:   sessionToken,
        Expires: expiresAt,
    })

    log.Println("login success")

    by, _ := json.Marshal(map[string]interface{}{
        "to": "http://localhost:8085/users",
    })

    w.Write(by)
}

我使用json响应而不是http.重新使用

function handleSubmit(evt) {
            evt.preventDefault();
            let form = evt.target;
            let data = new FormData(form);
            if (data.get("username") != null && data.get("username") != "") {
                $.ajax({
                    url: 'http://localhost:8085/login',
                    method: 'post',
                    data: JSON.stringify(Object.fromEntries(data)),
                    dataType: 'json',
                    success: (resp) => {
                        if (resp.to) {
                            window.location.href = resp.to;
                        }
                    },
                    error: (resp) => {
                        console.log("An error occurred. Please try again");
                        console.log(resp)
                    }
                });
            }
            return false
        }

Go相关问答推荐

gorm如何声明未自动更新的unix时间戳米尔斯字段

Gorm foreign 密钥

如何复制*C.char?

Makefilego version和read命令

为什么 `go mod` 占用了另一个磁盘上的空间而不是我的 GOPATH?

在运行时更改 Go lang slog 的日志(log)级别

如何使用gosdk在Dynamodb中进行UpdateItem时,将ValueBuilder对象声明为StringSet类型?

为什么 net/http 不遵守超过 30 秒的超时持续时间?

在本地 go 应用程序上获取秘密的正确策略

在 .go 文件中运行一个函数和在 Go 模板中调用它有什么区别?

regex.ReplaceAll 但如果替换则添加相同数量的字符

无法使用 gocsv 读取引用字段

Go http.FileServer 给出意外的 404 错误

如何在自定义验证函数中获取 struct 名称

从 os.stdout 读取

对所有标志进行 ORing 的简短方法

如何优雅地映射到 Go 中返回可变长度数组的方法?

Unescape 在 rss 中两次逃脱了标题

具有多个嵌入式 struct 的 Go MarshalJSON 行为

try 创建新的 etcdv3 客户端时出现pc error: code = Unavailable desc = error reading from server: EOF