Java 单点登录解决方案

Java 单点登录 (SSO) 有以下几种解决方案:

  1. 基于令牌(Token)的 SSO:用户在登录成功后,得到一个令牌,然后该令牌被用于访问其他相互信任的应用程序。Shiro 和 Spring Security 都支持基于令牌的 SSO。

  2. 基于代理(Proxy)的 SSO:一个代理服务器接收来自用户的请求,并将其重定向到适当的应用程序,并将用户身份验证信息传递给该应用程序。常见的代理服务器包括 Apache HTTP Server、Nginx 等。

  3. 基于中央认证授权(Central Authentication Authorization, CAS) 的 SSO:CAS 是一种开源的单点登录协议,它使用令牌来实现 SSO,可以与各种应用程序进行集成。CAS 服务器负责验证用户身份并生成令牌,应用程序则只需检查令牌即可。

  4. 基于安全标记(Security Assertion Markup Language, SAML) 的 SSO:SAML 是一种 XML 标记语言,用于在不同的应用程序之间交换用户身份验证和授权数据。当用户在一个应用程序上进行身份验证时,SAML 将会生成一个安全标记,并将其发送到其他应用程序以完成 SSO。

  5. OAuth 和 OpenID Connect:OAuth 用于授权,OpenID Connect 则用于身份验证。它们都是基于令牌的 SSO 解决方案,被广泛应用于第三方身份验证和授权领域。

以下是一些使用 Java 编写基于 Spring Security 的简单 SSO 示例

基于 Cookie 的 SSO


// 配置认证中心
@Configuration
@EnableWebSecurity
public class AuthServerConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login")
                .and()
                .logout().logoutSuccessUrl("/login").invalidateHttpSession(true)
                .deleteCookies("JSESSIONID", "MYAPPID");
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

// 配置子应用
@Configuration
public class SubAppConfig {
    // ...
    @RequestMapping("/index")
    public String index() {
        return "index";
    }

    @RequestMapping("/sub/login")
    public String subLogin(HttpServletRequest request, HttpServletResponse response) {
        // 检查是否已经登录,如果已经登录就不需要再次重定向到认证中心了
        if (request.getCookies() != null) {
            for (Cookie cookie : request.getCookies()) {
                if ("MYAPPID".equals(cookie.getName())) {
                    return "index";
                }
            }
        }

        // 未登录则跳转到认证中心进行认证
        response.sendRedirect("http://authserver.com/login?redirect_uri=http://subapp.com/sub/login/callback");
        return null;
    }

    @RequestMapping("/sub/login/callback")
    public String subLoginCallback(HttpServletRequest request, HttpServletResponse response) {
        // 认证中心认证成功后会重定向到此接口,携带认证令牌
        String token = request.getParameter("token");

        // 将认证令牌保存为 Cookie,并跳转回子应用首页
        Cookie cookie = new Cookie("MYAPPID", token);
        cookie.setPath("/");
        cookie.setMaxAge(24 * 60 * 60);
        response.addCookie(cookie);
        return "index";
    }
}

基于JWT的SSO

// 配置认证中心
@Configuration
@EnableWebSecurity
public class AuthServerConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login")
                .and()
                .logout().logoutSuccessUrl("/login").invalidateHttpSession(true)
                .deleteCookies("JSESSIONID");
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

// 配置子应用
@Configuration
public class SubAppConfig {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${authserver.url:http://authserver.com}")
    private String authServerUrl;

    @Value("${jwt.secret}")
    private String jwtSecret;

    @RequestMapping("/index")
    public String index(HttpServletRequest request) {
        String token = getTokenFromCookie(request);
        String username = getUsernameFromToken(token);

        // ...
    }

    @RequestMapping("/sub/login")
    public String subLogin(HttpServletRequest request, HttpServletResponse response) {
        // 检查是否已经登录,如果已经登录就不需要再次重定向到认证中心了
        String token = getTokenFromCookie(request);
        if (StringUtils.isNotEmpty(token)) {
            return "index";
        }

        // 未登录则跳转到认证中心进行认证
        response.sendRedirect(authServerUrl + "/login?redirect_uri=http://subapp.com/sub/login/callback");
        return null;
    }

    @RequestMapping("/sub/login/callback")
    public String subLoginCallback(HttpServletRequest request, HttpServletResponse response) {
        // 认证中心认证成功后会重定向到此接口,携带 JWT
        String jwt = request.getParameter("jwt");

        // 验证 JWT 签名,并解析出用户信息
        Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(jwt).

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值