我正在尝试修改我在不同地方在线找到的 Keycloak 和 Spring Boot 教程中的代码(代码看起来已重复)。无论如何,尽管 Keycloak 保护了正确的 URL 并且 Spring Security 提供了便利,但在尝试检索 Principal 时,它返回为 null。这是我的 application.properties 文件:
keycloak.auth-server-url=http://localhost:9090/auth
keycloak.realm=<some realm>
keycloak.resource=<some resource>
keycloak.ssl-required=external
keycloak.public-client=true
keycloak.principal-attribute=preferred_username
keycloak.use-resource-role-mappings=true
server.port=8100
这是我的 SecurityConfig.java 文件(来自教程的原始文件):
package com.bme.keycloakdemo.configuration;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
// Submits the KeycloakAuthenticationProvider to the AuthenticationManager
@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();
}
// Specifies the session authentication strategy
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/demo*")
.hasRole("user")
.anyRequest()
.permitAll();
}
}
我的网络 Controller 如下:
package com.bme.keycloakdemo.controllers;
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/demo")
public class DemoController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@GetMapping(value = "/first", produces = {MediaType.APPLICATION_JSON_VALUE})
public String first(Principal principal) {
logger.info("WE GOT HERE");
String retval = "WE GOT HERE! ";
if (principal != null) {
retval += principal.toString();
}
else {
retval += "PRINCIPAL IS NULL";
}
return retval;
}
@GetMapping(value = "/second", produces = {MediaType.APPLICATION_JSON_VALUE})
public String second(Principal principal) {
logger.info("WE GOT HERE");
String retval = "WE GOT HERE! " + principal.getName();
return retval;
}
@GetMapping(value = "/third", produces = {MediaType.APPLICATION_JSON_VALUE})
public String third(HttpServletRequest request) {
logger.info("WE GOT HERE");
Principal principal = request.getUserPrincipal();
String retval = "WE GOT HERE! ";
if (principal != null) {
retval += principal.toString();
}
else {
retval += "PRINCIPAL IS NULL";
}
return retval;
}
}
最后,这是我的 Maven 配置,以防它有所作为:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.batman-evolution</groupId>
<artifactId>keycloakjournal</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>keycloakjournal</name>
<description>Journal Secured with Keycloak</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.16.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<keycloak.version>3.4.0.Final</keycloak.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>${keycloak.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
所以回顾一下这个问题,我希望从 Keycloak 获得 Principal。我目前正在使用 Spring Security 来返回 Principal,但只要 Principal 可用,我真的不关心一种或另一种方式。谢谢你的帮助!
最佳答案
这对我有用:
@GetMapping("/details")
public MyUserDetails getUserDetails(Principal principal) {
KeycloakAuthenticationToken kp = (KeycloakAuthenticationToken) principal;
SimpleKeycloakAccount simpleKeycloakAccount = (SimpleKeycloakAccount) kp.getDetails();
AccesToken token = simpleKeycloakAccount.getKeycloakSecurityContext().getToken();
return new MyUserDetails(token.getGivenName(), token.getFamilyName(), token.getEmail());
}
关于spring-boot - 如何从 Keycloak 保护的 Spring Boot 应用程序中获取 Principal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53586558/