实现单点登录(Single Sign-On,SSO)通常需要在前端和后端进行协同工作,以下是一般的实现思路:
**前端部分:
** 1. 用户在前端页面发起登录请求,通常是向认证服务器发送登录信息(如用户名和密码)。
2. 登录成功后,认证服务器返回一个令牌(Token)给前端,通常是通过设置 Cookie 或者在请求的响应头中携带。
3. 前端在后续的请求中,自动携带这个令牌(例如在 Cookie 中或者请求头中)到后端服务。 **后端部分:
** 1. 后端服务接收到前端的请求后,首先检查请求中携带的令牌。
2. 后端服务与认证服务器进行通信,验证令牌的有效性。
3. 如果令牌有效,后端服务允许用户访问受保护的资源,并进行相应的业务处理。
4. 如果令牌无效或已过期,后端服务返回错误信息,前端引导用户重新登录。
为了实现上述功能,可能会用到以下技术和框架:
1. 常见的认证协议,如 OAuth 、 OpenID Connect 等。
2. 后端框架,如 Spring Security(Java)、Django (Python)等,它们通常提供了对单点登录的支持和集成。
3. 数据库或缓存来存储用户会话和令牌相关信息。 实现单点登录需要综合考虑安全性、性能、扩展性等多方面的因素,并根据具体的业务需求和技术架构进行选择和优化。
咱们一个一个的来,先实现第一个需求:
用户在前端页面发起登录请求,通常是向认证服务器发送登录信息(如用户名和密码)。
用vue代码表示
<template>
<div>
<h2>登录</h2>
<form @submit.prevent="login">
<label for="username">用户名:</label>
<input type="text" id="username" v-model="username" /><br><br>
<label for="password">密码:</label>
<input type="password" id="password" v-model="password" /><br><br>
<button type="submit">登录</button>
</form>
</div>
</template>
<script setup>
import { ref } from 'vue';
const username = ref('');
const password = ref('');
const token = ref('');
const login = async () => {
const data = {
username: username.value,
password: password.value
};
try {
const response = await fetch('http://your-auth-server.com/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (response.ok) {
const result = await response.json();
token.value = result.token;
document.cookie = `token=${token.value}`;
} else {
throw new Error('登录失败');
}
} catch (error) {
console.error('发生错误:', error);
}
};
</script>
后端用go zero代码表示
package main
import (
"fmt"
"net/http"
"time"
)
// 模拟认证服务器的验证接口
func validateToken(token string) bool {
// 这里假设简单的验证规则,实际中可能会与数据库或其他存储进行交互
return token == "valid_token"
}
func loginHandler(w http.ResponseWriter, r *http.Request) {
username := r.FormValue("username")
password := r.FormValue("password")
// 模拟验证用户名和密码
if username == "valid_user" && password == "valid_password" {
token := generateToken()
// 通过设置响应头或 Cookie 返回令牌给前端
w.Header().Set("Authorization", "Bearer " + token)
http.SetCookie(w, &http.Cookie{Name: "token", Value: token, Expires: time.Now().Add(24 * time.Hour)})
// 与认证服务器通信验证令牌有效性
if validateToken(token) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("登录成功"))
return
}
}
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("登录失败"))
}
func generateToken() string {
// 这里简单生成一个示例令牌
return "valid_token"
}
func main() {
http.HandleFunc("/login", loginHandler)
http.ListenAndServe(":8080", nil)
}