本文介紹了帶有Keyloak的Spring應用程序返回401錯誤的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我正嘗試通過Keyshaak訪問一個Spring App,但我總是收到401未經授權的錯誤。基本上,我有一個單獨運行良好的聊天模塊,但一旦我添加Keyloak,我就無法訪問應用程序,因為那個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/
我有一個第一個接口(沒有密鑰遮蓋安全性),它有一個指向我的服務的鏈接,它是localhost:port/index/{topicName}
。現在,當我點擊該鏈接時,我應該看到Keyloak身份驗證屏幕,但我得到的卻是401錯誤。
我已經檢查了我的請求頭,將一個HttpServletRequest作為參數添加到我的displayMessage
方法中,并且我實際上可以在我的IDE控制臺中顯示ACCESS_TOKEN和X-AUTH-TOKEN。但似乎當我點擊該鏈接時,它發送的請求沒有令牌。
以下是我的控制器方法(我的控制器類用@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";
}
我的Keyloak配置文件的靈感來自于我讀過的tuto,所以其中可能有一個我不知道的錯誤(不確定方法access
和hasRole
的區別是什么):
@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());
}
我真的不知道我還應該做什么更改才能使其正常工作,但我相信其中一定有什么不對勁。但我認為,如果我在嘗試訪問我的服務時可以使用Keyloak身份驗證屏幕,這就可以了。
推薦答案
我收到了相同的錯誤,需要再次檢查的一件事是auth-server-url
對于服務器和客戶端獲取令牌是相同的。
即,如果一個是DNS名稱,一個是IP地址,則不會授權。(在我的例子中,我有本地主機和127.0.0.1,因此授權失敗)
服務器,src/main/Resources/Applation.yml
郵遞員/客戶:
這篇關于帶有Keyloak的Spring應用程序返回401錯誤的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,