由于网上博客大部分都只有登陆没有退出,自己花了一些时间研究了一下,这里将相关内容进行记录,基于Keyclaok 20的版本,实现springboot服务单点登录与退出
一、依赖
XML
<!-- 在父工程中 -->
<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配置
这个是主要的,用设置拦截器实现登陆与退出
java
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);
}
};
}
}