在Java中实现单点登录(Single Sign-On, SSO),可以使用以下几种方法:
- 使用Java Servlet Filter
创建一个自定义的Servlet Filter,用于拦截所有请求并将其重定向到单点登录服务器。当用户从单点登录服务器返回时,Filter将检查返回的认证信息和Cookie,然后将用户重定向到原始请求的URL。
public class SSOSFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; // 检查用户是否已经登录 HttpSession session = httpRequest.getSession(false); if (session != null && session.getAttribute("user") != null) { // 用户已登录,重定向到原始请求的URL chain.doFilter(request, response); } else { // 用户未登录,重定向到单点登录服务器 String loginUrl = "http://example.com/login"; httpResponse.sendRedirect(loginUrl); } } // 其他方法... }
- 使用Java EE中的JAAS (Java Authentication and Authorization Service)
JAAS是一个用于Java应用程序的认证和授权框架。你可以使用JAAS实现单点登录,通过配置一个LoginContext来处理用户登录和认证。
首先,创建一个JAAS登录配置文件(例如:jaas.conf):
MyLoginContext { com.example.MyLoginModule required debug=true; };
然后,在应用程序中使用JAAS进行认证:
public class JaasExample { public static void main(String[] args) { try { // 设置系统属性 System.setProperty("java.security.auth.login.config", "path/to/jaas.conf"); // 创建LoginContext LoginContext loginContext = new LoginContext("MyLoginContext", new CallbackHandlerImpl()); // 登录用户 loginContext.login(); // 获取认证信息 Subject subject = loginContext.getSubject(); String username = (String) subject.getPrincipal(); // 执行业务逻辑... // 登出用户 loginContext.logout(); } catch (LoginException e) { e.printStackTrace(); } } }
- 使用Spring Security
Spring Security是一个强大的安全框架,支持单点登录和其他安全功能。你可以使用Spring Security配置一个认证过滤器,将所有请求重定向到单点登录服务器。
首先,添加Spring Security依赖到你的项目中。然后,创建一个自定义的AuthenticationFilter,继承UsernamePasswordAuthenticationFilter
,并重写attemptAuthentication
方法。
public class SSOAuthFilter extends UsernamePasswordAuthenticationFilter { @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { // 获取请求中的用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); // 创建认证请求 UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // 设置认证请求到AuthenticationManager setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } }
接下来,配置Spring Security过滤器链,将自定义的SSOAuthenticationFilter
添加到过滤器链中。
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll() .and() .addFilterBefore(new SSOAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); } }
最后,创建一个单点登录控制器,处理用户登录请求,并将认证信息存储在Session中。
@Controller public class LoginController { @GetMapping("/login") public String login(Model model) { // 这里可以添加表单渲染逻辑 return "login"; } @PostMapping("/login") public String loginSubmit(@RequestParam("username") String username, @RequestParam("password") String password, HttpSession session) { // 验证用户名和密码 boolean isAuthenticated = authenticate(username, password); if (isAuthenticated) { // 将用户信息存储在Session中 session.setAttribute("user", username); // 重定向到原始请求的URL return "redirect:/original-request-url"; } else { // 登录失败,重定向到登录页面 return "login"; } } private boolean authenticate(String username, String password) { // 这里可以添加实际的认证逻辑,例如查询数据库 return "admin".equals(username) && "password".equals(password); } }
这样,当用户访问受保护的资源时,将被重定向到单点登录服务器。用户登录成功后,将返回到原始请求的URL,并携带认证信息。应用程序可以从Session中获取认证信息,进行后续的业务逻辑处理。