目录
前言:
基于 Token 的 SSO 实现单点登录
实现 SSO 的单点登录通常需要以下步骤:
第一步:
创建一个 UserService 类,用于处理用户登录和生成 Token。
创建一个 TokenCache 类,用于存储 Token 和对应的用户信息。
在 Auth Center 中创建一个 LoginController 类,用于处理用户登录请求。
创建一个应用(App)项目,用于演示单点登录。
在 App 中创建一个 LoginController 类,用于处理用户登录请求。
在 App 中创建一个 LogoutController 类,用于处理用户注销请求。
在 App 中创建一个 AuthFilter 类,用于拦截请求并验证 Token。
在 App 中配置 AuthFilter。
单点登录流程:
AppConfig 和 AuthFilter 两个类在单点登录流程中作用。
前言:
🔣方法千千万,单点登录不一般,记录一个小笔记,虽然生活很累,但是依然励志前行
基于 Token 的 SSO 实现单点登录
SSO(Single Sign-On,单点登录)是一种身份验证机制,它允许用户使用一组凭据(例如用户名和密码)登录到多个应用程序或系统中,而无需在每个应用程序或系统中单独进行身份验证。在 SSO 中,用户只需要登录一次,就可以访问所有与 SSO 集成的应用程序或系统,这样可以提高用户体验和安全性。
实现 SSO 的单点登录通常需要以下步骤:
-
创建一个认证中心(Auth Center)应用程序,用于处理用户身份验证和生成 Token。
-
在 Auth Center 中创建一个用户数据库或集成现有的用户数据库,用于存储用户信息和凭据。
-
在 Auth Center 中实现身份验证机制,例如用户名和密码验证、双因素身份验证等。
-
在 Auth Center 中生成一个 Token,并将 Token 存储到缓存中,以便后续验证。
-
在每个需要集成 SSO 的应用程序中,创建一个 Token 验证机制,用于验证 Token 是否有效。
-
在每个应用程序中,创建一个登录页面,用于接收用户凭据并向 Auth Center 发送身份验证请求。
-
在每个应用程序中,将 Token 存储到 Cookie 或其他存储介质中,以便后续验证。
-
在每个应用程序中,创建一个拦截器或过滤器,用于拦截请求并验证 Token。
-
在每个应用程序中,根据 Token 中的用户信息显示对应的页面或资源。
-
在每个应用程序中,创建一个注销机制,用于删除 Token 并注销用户。
通过以上步骤,可以实现基于 Token 的 SSO 单点登录。在这种方案中,用户只需要登录一次,就可以访问所有与 SSO 集成的应用程序,这样可以提高用户体验和安全性。
第一步:
-
创建一个认证中心(Auth Center)项目,用于处理用户登录和生成 Token。
-
在 Auth Center 中创建一个 User 类,用于存储用户信息。
public class User {
private String username;
private String password;
// 其他用户信息
// 构造函数、getter 和 setter 方法
}
-
创建一个 UserService 类,用于处理用户登录和生成 Token。
public class UserService {
private static final Map<String, User> userMap = new HashMap<>();
static {
// 初始化用户数据
User user1 = new User("user1", "password1");
User user2 = new User("user2", "password2");
userMap.put(user1.getUsername(), user1);
userMap.put(user2.getUsername(), user2);
}
public static String login(String username, String password) {
User user = userMap.get(username);
if (user != null && user.getPassword().equals(password)) {
// 生成 Token
String token = UUID.randomUUID().toString();
// 将 Token 存储到缓存中
TokenCache.put(token, user);
return token;
}
return null;
}
public static User getUserByToken(String token) {
return TokenCache.get(token);
}
}
-
创建一个 TokenCache 类,用于存储 Token 和对应的用户信息。
public class TokenCache {
private static final Map<String, User> tokenMap = new ConcurrentHashMap<>();
public static void put(String token, User user) {
tokenMap.put(token, user);
}
public static User get(String token) {
return tokenMap.get(token);
}
}
-
在 Auth Center 中创建一个 LoginController 类,用于处理用户登录请求。
@RestController
public class LoginController {
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
String token = UserService.login(username, password);
if (token != null) {
return token;
}
return "login failed";
}
}
-
创建一个应用(App)项目,用于演示单点登录。
-
在 App 中创建一个 HomeController 类,用于处理首页请求。
@RestController
public class HomeController {
@GetMapping("/")
public String home(HttpServletRequest request) {
String token = request.getHeader("token");
User user = UserService.getUserByToken(token);
if (user != null) {
return "Welcome, " + user.getUsername();
}
return "Please login first";
}
}
-
在 App 中创建一个 LoginController 类,用于处理用户登录请求。
@RestController
public class LoginController {
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
// 向认证中心发送登录请求
String url = "http://localhost:8080/login?username=" + username + "&password=" + password;
RestTemplate restTemplate = new RestTemplate();
String token = restTemplate.postForObject(url, null, String.class);
if (token != null) {
// 将 Token 存储到 Cookie 中
Cookie cookie = new Cookie("token", token);
cookie.setPath("/");
cookie.setMaxAge(3600);
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
response.addCookie(cookie);
return "login success";
}
return "login failed";
}
}
-
在 App 中创建一个 LogoutController 类,用于处理用户注销请求。
@RestController
public class LogoutController {
@GetMapping("/logout")
public String logout(HttpServletRequest request) {
// 从 Cookie 中获取 Token
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("token")) {
String token = cookie.getValue();
// 从缓存中删除 Token
TokenCache.get(token);
// 删除 Cookie
cookie.setMaxAge(0);
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
response.addCookie(cookie);
return "logout success";
}
}
}
return "logout failed";
}
}
-
在 App 中创建一个 AuthFilter 类,用于拦截请求并验证 Token。
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String token = httpRequest.getHeader("token");
User user = UserService.getUserByToken(token);
if (user != null) {
chain.doFilter(request, response);
} else {
httpResponse.sendRedirect("/login");
}
}
}
-
在 App 中配置 AuthFilter。
@Configuration
public class AppConfig {
@Bean
public FilterRegistrationBean<AuthFilter> authFilterRegistration() {
FilterRegistrationBean<AuthFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new AuthFilter());
registration.addUrlPatterns("/*");
registration.setName("authFilter");
registration.setOrder(1);
return registration;
}
}
authFilterRegistration()
方法的作用是将 AuthFilter 过滤器注册到应用程序中,并指定过滤器的执行顺序和 URL 模式,以确保该过滤器能够正确地拦截请求并验证 Token。- 启动 Auth Center 和 App 两个项目,访问 App 的首页,会提示需要登录,点击登录按钮,输入用户名和密码,登录成功后会跳转到首页,显示欢迎信息。在其他浏览器或标签页中访问 App 的首页,会自动跳转到登录页面。在已登录的浏览器或标签页中访问 App 的其他页面,会自动跳转到对应页面,无需再次登录。
单点登录流程:
-
用户在 App 中访问需要登录的页面,如果没有登录,则跳转到登录页面。
-
用户在登录页面输入用户名和密码,App 向 Auth Center 发送登录请求。
-
Auth Center 验证用户名和密码,如果验证通过,则生成一个 Token,并将 Token 存储到缓存中。
-
Auth Center 返回 Token 给 App。
-
App 将 Token 存储到 Cookie 中,并跳转到首页。
-
用户在 App 中访问其他页面时,App 会从 Cookie 中获取 Token,并向 Auth Center 发送 Token 验证请求。
-
Auth Center 验证 Token,如果验证通过,则返回用户信息。
-
App 根据用户信息显示对应页面。
-
用户在任意浏览器或标签页中访问 App,如果已经登录,则无需再次登录,直接跳转到对应页面。
AppConfig 和 AuthFilter 两个类在单点登录流程中作用。
- AppConfig 类是用来配置 AuthFilter 的,AuthFilter 是一个过滤器,用于拦截请求并验证 Token。在单点登录流程中,用户在访问需要登录的页面时,AuthFilter 会拦截请求并检查是否存在 Token,如果存在,则验证 Token 是否有效,如果有效,则允许用户访问页面,否则跳转到登录页面。因此,AuthFilter 在单点登录流程中起到了验证 Token 的作用。
- 而 AppConfig 类则是用来配置 AuthFilter 的,它通过创建一个 FilterRegistrationBean 对象来注册 AuthFilter,并指定了过滤器的 URL 模式、名称和执行顺序。在单点登录流程中,AppConfig 类的作用是将 AuthFilter 注册到应用程序中,并指定x过滤器的执行顺序,以确保 AuthFilter 在其他过滤器之前执行。因此,AppConfig 在单点登录流程中起到了注册和配置 AuthFilter 的作用。