Springboot继承Keycloak实现单点登录与退出功能

 更新时间:2023年08月29日 09:51:35   作者:xxb249  
这篇文章主要介绍了Springboot继承Keycloak实现单点登陆与退出,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

什么是 keycloak

keycloak是一个开源的进行身份认证和访问控制的软件。是由Red Hat基金会开发的,我们可以使用keycloak方便的向应用程序和安全服务添加身份认证,非常的方便。基于 Java 开发,支持多种数据库。

由于网上博客大部分都只有登陆没有退出,自己花了一些时间研究了一下,这里将相关内容进行记录,基于Keyclaok 20的版本,实现springboot服务单点登录与退出

一、依赖

<!-- 在父工程中 -->
<dependencyManagement>
    <dependencies>
        <!-- 导入依赖 -->
        <dependency>
            <groupId>org.keycloak.bom</groupId>
            <artifactId>keycloak-adapter-bom</artifactId>
            <version>22.0.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<!-- 在子工程中 -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-spring-security-adapter</artifactId>
    </dependency>
</dependencies>

二、keycloak配置

这个是主要的,用设置拦截器实现登陆与退出

package com.example.basic.conf;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class KeycloakSecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }
    @Bean
    public org.keycloak.adapters.KeycloakConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
            .logout()
                 //拦截logout请求
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .addLogoutHandler(keycloakLogoutHandler())
                .logoutSuccessHandler(logoutSuccessHandler())
                .deleteCookies("JSESSIONID")
            .and()
             //设置哪些可以忽略掉授权
            .authorizeRequests()
                .antMatchers("/user/login", "/token/generate",
                    "/access/**", "/js/**","/css/**","/fonts/**", "/index.html", "/error").permitAll()
                 //除了上面忽略掉授权请求,剩下所有必须经过授权才可以访问
                .antMatchers("/**").authenticated()
            .and().cors()
            .and().csrf().disable();
    }
    //处理logout自动跳转请求
    private LogoutSuccessHandler logoutSuccessHandler() {
        return new LogoutSuccessHandler() {
            @Override
            public void onLogoutSuccess(HttpServletRequest httpServletRequest,
                    HttpServletResponse httpServletResponse, Authentication authentication)
                    throws IOException, ServletException {
                KeycloakAuthenticationToken keycloakAuthenticationToken = (KeycloakAuthenticationToken)authentication;
                KeycloakSecurityContext keycloakSecurityContext =
                        keycloakAuthenticationToken.getAccount().getKeycloakSecurityContext();
                String idTokenHint = keycloakSecurityContext.getIdTokenString();
                String issuer = keycloakSecurityContext.getIdToken().getIssuer();
                String keycloakBaseUrl = issuer + "/protocol/openid-connect/logout";
                String postLogoutRedirectUri = httpServletRequest.getScheme() + "://" + httpServletRequest.getHeader("host");
                String logoutUrl = keycloakBaseUrl + "?post_logout_redirect_uri=" + postLogoutRedirectUri + "&id_token_hint=" + idTokenHint;
                // Do logout by redirecting to Keycloak logout
                httpServletResponse.sendRedirect(logoutUrl);
            }
        };
    }
}

到此这篇关于Springboot继承Keycloak实现单点登录与退出功能的文章就介绍到这了,更多相关Springboot Keycloak单点登录与退出内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Elasticsearch常见字段映射类型之scaled_float解读

    Elasticsearch常见字段映射类型之scaled_float解读

    这篇文章主要介绍了Elasticsearch常见字段映射类型之scaled_float解读。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 运用java以及循环打印菱形详细实例代码

    运用java以及循环打印菱形详细实例代码

    最近在看算法书的时候,看到有打印上三角的算法,然后要举一反三,下面这篇文章主要介绍了运用java以及循环打印菱形的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-10-10
  • Spring Cloud Eureka 搭建 & 集群方式

    Spring Cloud Eureka 搭建 & 集群方式

    这篇文章主要介绍了Spring Cloud Eureka 搭建 & 集群方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Java实现JWT令牌的示例代码

    Java实现JWT令牌的示例代码

    JWT是一种无状态认证方案,用于前后端分离项目,后端生成包含用户信息的token,前端保存并随请求头携带,后端通过验证token签名、有效期等确保安全,实现跨服务身份认证,感兴趣的可以了解一下
    2025-09-09
  • Java二维数组实战案例

    Java二维数组实战案例

    这篇文章主要介绍了Java二维数组,结合具体案例形式分析了java二维数组定义、遍历、计算等相关操作技巧,需要的朋友可以参考下
    2019-08-08
  • java实现支付宝退款功能

    java实现支付宝退款功能

    这篇文章主要为大家详细 介绍了java实现支付宝退款功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-09-09
  • 通过简单方法实现spring boot web项目

    通过简单方法实现spring boot web项目

    这篇文章主要介绍了通过简单方法实现spring boot web项目,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • elasticsearch集群查询超10000的解决方案

    elasticsearch集群查询超10000的解决方案

    ES为了避免用户的过大分页请求造成ES服务所在机器内存溢出,默认对深度分页的条数进行了限制,默认的最大条数是10000条,这篇文章主要给大家介绍了关于elasticsearch集群查询超10000的解决方案,需要的朋友可以参考下
    2024-08-08
  • 解释为什么Java中“1000==1000”为false而”100==100“为true

    解释为什么Java中“1000==1000”为false而”100==100“为true

    在日常编程中,我们经常遇到一些看似简单却隐藏着复杂逻辑的问题,这篇文章主要介绍了解释为什么Java中“1000==1000”为false而”100==100“为true,需要的朋友可以参考下
    2024-01-01
  • 浅析如何在Java应用中优雅的发送短信

    浅析如何在Java应用中优雅的发送短信

    很多业务场景里,我们都需要发送短信,比如登陆验证码、告警、营销通知、节日祝福等等,这篇文章,我们聊聊 Java 应用中如何优雅的发送短信,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2023-11-11

最新评论