spring boot 3.2 整合 keycloak

背景

项目中用到 keycloak,因此其他所有管理页面要集成 keycloak 做统一登录认证。

Keycloak 侧配置

容器方式启动 keycloak 服务端

docker run -d --name mykeycloak -p 8080:8080         -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin         keycloak         start-dev

注意如果不能联网的话需要要提前下载好镜像。

创建域

启动后,浏览器登录 http://ip:8080,默认用户名密码:admin/admin
创建域:client
在这里插入图片描述
在这里插入图片描述

创建客户端

在这里插入图片描述
打开客户端认证
在这里插入图片描述
设置登录成功后的重定向地址(这里可以添加多个)
在这里插入图片描述
获取密钥,这个在配置 spring boot 时需要
在这里插入图片描述

创建用户

这里的用户用于统一认证。
在这里插入图片描述
设置登录密码
在这里插入图片描述

Spring boot 侧实现

keycloak 有好几种方式集成 spring boot,例如(https://www.keycloak.org/docs/latest/securing_apps/index.html):
在这里插入图片描述

之前使用的是 Adapter 方式,但是官方已经废弃了,现在统一用 oauth2。

引入依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

如果没有特殊要求,则直接使用 spring boot 中配置的版本即可,不用单独设置版本。

添加 Security Filter

package casuallc.github.io;

import static casuallc.github.io.global.Constants.IGNORE_AUTHENTICATION_RESOURCES;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

@Configuration
@EnableWebSecurity
@Slf4j
public class CustomSecurityConfiguration {

    @Value("${security.enabled}")
    private boolean securityEnabled;
    @Value("${security.same-site.enabled}")
    private boolean securitySameSiteEnabled;
    @Value("${security.keycloak.enabled:false}")
    private boolean keyCloakEnabled;
    @Value("${security.oauth2.enabled:false}")
    private boolean oauth2Enabled;
    @Value("${security.oauth2.logout.url:}")
    private String oauth2LogoutUrl;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        if (!securitySameSiteEnabled) {
            http.headers(AbstractHttpConfigurer::disable);
        } else {
            http.headers(header -> header.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin));
        }

        if (securityEnabled) {
            CookieCsrfTokenRepository csrfTokenRepository = new CookieCsrfTokenRepository();
            csrfTokenRepository.setCookieCustomizer(cookie -> cookie.secure(true)
                    .maxAge(86400));
            http.csrf(csrf -> csrf.ignoringRequestMatchers(IGNORE_AUTHENTICATION_RESOURCES)
                    .csrfTokenRepository(csrfTokenRepository));
            return http.build();
        }

        // 使用其他方式认证时关闭 csrf
        http.csrf(AbstractHttpConfigurer::disable);

        if (keyCloakEnabled || oauth2Enabled) {
            http.authorizeHttpRequests(a -> a
                            .requestMatchers(IGNORE_AUTHENTICATION_RESOURCES)
                            .permitAll()
                            .anyRequest()
                            .authenticated())
                    .oauth2Login(Customizer.withDefaults());
            if (StringUtils.isNotBlank(oauth2LogoutUrl)) {
                http.logout(r -> r.logoutSuccessUrl(oauth2LogoutUrl));
            }
            log.info("{} enabled ...", keyCloakEnabled ? "Keycloak" : "Oauth2");
            return http.build();
        }

        log.info("Security CSRF disabled ...");
        return http.build();
    }
}

IGNORE_AUTHENTICATION_RESOURCES 配置了哪些请求不需要认证,比如登录地址。

添加认证配置

### --- 认证配置(需要关闭security.same-site.enabled和security.enabled) --- ###
security.keycloak.enabled=true
spring.security.oauth2.client.provider.external.issuer-uri=http://keycloak:8080/realms/test

spring.security.oauth2.client.registration.external.provider=external
# 客户端名称
spring.security.oauth2.client.registration.external.client-name=client
# 客户端名称
spring.security.oauth2.client.registration.external.client-id=client
spring.security.oauth2.client.registration.external.client-secret=配置在 keycloak client 页面获取的密钥
spring.security.oauth2.client.registration.external.scope=openid,offline_access,profile
spring.security.oauth2.client.registration.external.authorization-grant-type=authorization_code

获取登录用户

在使用 keycloak 登录后,在 request 中可以获取到用户信息

public static String getUserFromOauth2(HttpServletRequest request) {
	OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) request.getUserPrincipal();
	if (token == null) {
		log.warn("Can not get keycloak user from request.");
		return null;
	}
	OAuth2User user = token.getPrincipal();
	if (user instanceof DefaultOidcUser oidcUser) {
		return oidcUser.getPreferredUsername();
	}
	if (user instanceof DefaultOAuth2User oAuth2User) {
		return oAuth2User.getName();
	}
	return user.getName();
}

最后

以上操作完成后,可以访问 spring boot 项目,会自动跳转到 keycloak 登录页面,登录成功后重定向到 spring boot 项目页面。

  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你好!关于Spring Boot集成Keycloak,你可以按照以下步骤进行操作: 1. 添加Keycloak依赖:在pom.xml文件中添加Keycloak的依赖项。例如: ```xml <dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-boot-starter</artifactId> </dependency> ``` 2. 配置application.properties:在Spring Boot的配置文件(application.properties)中添加以下Keycloak相关的配置信息: ```properties # Keycloak Server URL keycloak.auth-server-url=http://localhost:8080/auth # Keycloak Realm keycloak.realm=myrealm # Keycloak Client ID keycloak.resource=myclient # Keycloak Client Secret keycloak.credentials.secret=mysecret # Enable HTTPS server.ssl.enabled=true ``` 请确保将上述配置项中的URL、realm、client ID、client secret和其他相关信息设置为你的实际值。 3. 创建Keycloak配置类:创建一个Keycloak配置类,用于将KeycloakSpring Boot应用程序集成。例如: ```java @Configuration @EnableWebSecurity @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class) public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider(); keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(keycloakAuthenticationProvider); } @Bean public KeycloakSpringBootConfigResolver keycloakConfigResolver() { return new KeycloakSpringBootConfigResolver(); } @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http .authorizeRequests() .antMatchers("/api/public").permitAll() .antMatchers("/api/private").hasRole("user") .anyRequest().authenticated(); } } ``` 这个配置类继承了KeycloakWebSecurityConfigurerAdapter,并覆盖了一些方法,以满足你的应用程序的需求。请根据你的实际需求进行适当的修改。 4. 创建受保护的API:在你的应用程序中创建一些需要受到Keycloak保护的API。例如: ```java @RestController @RequestMapping("/api") public class ApiController { @GetMapping("/public") public String publicApi() { return "This is a public API."; } @GetMapping("/private") public String privateApi() { return "This is a private API."; } } ``` 在这个示例中,`/api/public`是一个公共API,不需要进行身份验证,而`/api/private`是一个私有API,需要用户进行身份验证才能访问。 5. 运行应用程序:现在,你可以运行你的Spring Boot应用程序,并尝试访问受保护的API。当访问私有API时,你将被重定向到Keycloak登录页面。 这只是一个简单的示例,你可以根据你的具体需求进行更复杂的配置。希望对你有所帮助!如有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值