gpt4 book ai didi

java - 带有 Keycloak 的 Spring 应用程序返回 401 错误

转载 作者:行者123 更新时间:2023-12-05 00:42:08 27 4
gpt4 key购买 nike

我正在尝试通过 Keycloak 访问 Spring 应用程序,但我总是收到 401 Unauthorized 错误。基本上我有一个单独工作的聊天模块,但是一旦我添加了 Keycloak,由于 401 错误,我无法访问该应用程序。我已经关注了大约 3 个教程,这些教程显示了与我所做的类似的事情,但我仍然不知道我做错了什么。

这是我应用的配置:

keycloak: 
enabled: true
realm: myReal
resource: myReal-api
public-client: true
bearer-only: true
auth-server-url: http://localhost:8080/auth
credentials:
secret: 82eXXXXX-3XXX-4XXX-XXX7-287aXXXXXXXX
principal-attribute: preferred_username
cors: true

localhost:port/ 我有第一个接口(interface)(没有 Keycloak 安全性),它有一个指向我的服务的链接,即 localhost:port/index/{topicName} 。现在,当我单击该链接时,我应该得到 Keycloak 身份验证屏幕,但我得到了 401 错误。

我检查了请求的 header ,将 HttpServletRequest 作为参数添加到我的 displayMessage 方法中,实际上我可以在我的 IDE 控制台中显示 access_token 和 X-Auth-Token。但似乎当我点击该链接时,它发送的请求没有 token 。

这是我的 Controller 方法(我的 Controller 类用 @Controller 注释:

@GetMapping(path = "/")
public String index() {
return "external";
}

@GetMapping(path = "/index/{topicName}",
produces = MediaType.APPLICATION_JSON_VALUE)
public String displayMessages(Model model,
@PathVariable String topicName) {

//HttpHeaders headers = new HttpHeaders();

//headers.set("Authorization", request.getHeader("Authorization"));
//header = request.getHeader("Authorization");
//System.out.println(" T O K E N "+request.getHeader("X-Auth-Token"));

projectServiceImpl.findByName(topicName);
List<Message> messages = messageServiceImpl.findAllMessagesByProjectName(topicName);
model.addAttribute("topic", topicName);
model.addAttribute("message",messages);

return "index";
}

我的 Keycloak 配置文件的灵感来 self 读过的 tuto,因此其中可能存在我不知道的错误(不确定方法 accesshasRole 是):

@Configuration
@ComponentScan(
basePackageClasses = KeycloakSecurityComponents.class,
excludeFilters = @ComponentScan.Filter(
type = FilterType.REGEX,
pattern = "org.keycloak.adapters.springsecurity.management.HttpSessionManager"))
@EnableWebSecurity
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {


private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);

@Bean
public HttpSessionIdResolver httpSessionIdResolver() { //replace HttpSessionStrategy
return HeaderHttpSessionIdResolver.xAuthToken();
}

//Registers the KeycloakAuthenticationProvider with the authentication manager.
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

try {
SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
grantedAuthorityMapper.setPrefix("ROLE_");
grantedAuthorityMapper.setConvertToUpperCase(true);

KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(grantedAuthorityMapper);

auth.authenticationProvider(keycloakAuthenticationProvider());

} catch(Exception ex) {
logger.error("SecurityConfig.configureGlobal: " + ex);

}

/*try {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}catch(Exception ex){
logger.error("SecurityConfig.configureGlobal: " +ex);
}*/
}

//Load Keycloak properties from service config-file
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}

//Defines the session authentication strategy.
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
//Public or Confidential application keycloak/OpenID Connect client
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
//Bearer mode only keycloak/OpenID Connect client without keycloak session -> stateless behavior
//return new NullAuthenticatedSessionStrategy();
}


@Override
protected void configure(HttpSecurity http) throws Exception
{
super.configure(http);
http.authorizeRequests()
//BEGIN
//USER -done to be tested

.antMatchers(HttpMethod.GET,"/index**").access("hasAuthority('ADMIN')")
.antMatchers(HttpMethod.GET,"/").access("hasAuthority('ADMIN')")
.antMatchers(HttpMethod.GET,"/").access("hasAnyAuthority('ADMIN','MANAGER','EXPERT','STANDARD')")



.anyRequest().authenticated()

.and()
.cors()
.and()
.csrf().disable()
//BEGIN Login/Logout
.formLogin()
.permitAll()//.successHandler(authenticationSuccessHandler) //
.and()
.logout()//.clearAuthentication(true) //Add .clearAuthentication(true) to logout()
//.logoutUrl("/custom-logout")
.addLogoutHandler(keycloakLogoutHandler())
//.addLogoutHandler(new LogoutHandlerImpl())
.clearAuthentication(true)
.invalidateHttpSession(true)
.permitAll();
//END Login/Logout

//BEGIN Session
http
.sessionManagement()
//.sessionCreationPolicy(SessionCreationPolicy.ALWAYS) //BY default IF_REQUIRED
.maximumSessions(1)
.maxSessionsPreventsLogin(false) // if true generate an error when user login after reaching maximumSession (SessionAuthenticationStrategy rejected the authentication object / SessionAuthenticationException: Maximum sessions of 1 for this principal exceeded)
//.expiredUrl("/auth/login")
.sessionRegistry(sessionRegistry());



}

@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AccessToken accessToken() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
return ((KeycloakSecurityContext) ((KeycloakAuthenticationToken) request.getUserPrincipal()).getCredentials()).getToken();
}

///BEGIN session
@Bean
public SessionRegistry sessionRegistry() {
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}


@Bean
public RegisterSessionAuthenticationStrategy registerSessionAuthStr( ) {
return new RegisterSessionAuthenticationStrategy( sessionRegistry( ) );
}

// Register HttpSessionEventPublisher
@Bean
public static ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}

我真的不知道我还应该改变什么才能让它工作,但我相信那里一定有什么问题。但我想如果我在尝试访问我的服务时可以有 Keycloak 身份验证屏幕,那就没问题了。

最佳答案

我收到了同样的错误,要仔细检查的一件事是 auth-server-url 对于服务器是相同的,而客户端获取 token 。

即如果一个是 dns 名称,一个是 IP 地址,它将不授权。 (在我的情况下,我有 localhost 和 127.0.0.1 所以授权失败)

服务器,src/main/resources/application.yml

enter image description here

postman /客户:

enter image description here

关于java - 带有 Keycloak 的 Spring 应用程序返回 401 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57477407/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com