当使用Keycloak登录时,Tomcat有时会回复403,有时不会

时间:2018-06-06 06:53:45

标签: java spring spring-boot spring-security keycloak

我有2个应用程序(Spring Boot和Spring MVC),它们都部署在Tocmcat中,如

localhost:9595/bootapp/   

localhost:9595/mvcapp/

我已将他们两人注册为Keycloak客户:

my_client

我有2个用户userA with role(MVC_USER,BOOT_USER)和userB with roles(BOOT_USER)

1.要注册启动应用程序,我在application.properties中使用了此配置:

keycloak.auth-server-url=http://10.60.6.34:8282/auth
keycloak.realm=IAP
keycloak.resource=my_client
keycloak.public-client=true
keycloak.principal-attribute=preferred_username

这是我的安全配置类:

 @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);
}

//keycloakConfigResolver: this defines that we want to use the Spring Boot properties file support instead of the default keycloak.json
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
    return new KeycloakSpringBootConfigResolver();
}

@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
    return new RegisterSessionAuthenticationStrategy(buildSessionRegistry());
}

@Bean
protected SessionRegistry buildSessionRegistry() {
    return new SessionRegistryImpl();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http
            .csrf()
            .disable()
            .authorizeRequests()
            .antMatchers("/user").hasRole("BOOT_USER")
            .antMatchers("/main").hasRole("uma_authorization");
}

@Autowired
public KeycloakClientRequestFactory keycloakClientRequestFactory;
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public KeycloakRestTemplate keycloakRestTemplate(){
    return new KeycloakRestTemplate(keycloakClientRequestFactory);
}


}`
  1. 要注册mvcapp,我将其添加到META-INF / context.xml文件中:

    <Context> <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/> </Context>

  2. 2.1。将keycloak.json添加到WEB-INF:

    {
     "realm": "IAP",
     "auth-server-url": "http://10.60.6.34:8282/auth",
     "resource": "my_app",
     "public-client": true,
     "confidential-port": 0,
     "principal-attribute":"preferred_username"
    }
    

    2.2。并将web.xml添加到WEB-INF,内容如下:

    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    
    
    
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>NSI</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>MVC_USER</role-name>
        </auth-constraint>
    </security-constraint>
    
    
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>this is ignored currently</realm-name>
    </login-config>
    
    <security-role>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <role-name>MVC_USER</role-name>
    </security-role>
    

    我的目标网页位于bootapp中,因此我的main.jsp文件包含重定向到mvcapp的链接。

    我的问题是:

    例如我输入:

    本地主机:9595 / BOOTAPP

    出现Keycloak的登录页面。我使用userB(只有BOOT_USER角色)登录,并显示来自bootapp的登陆页面main.jsp。当我尝试通过单击链接重定向到mvc应用程序时,Tomcat会按预期抛出403错误,因为userB没有获得MVC_USER角色。好!

    然后,当我在浏览器中输入这个url行时:

    http://localhost:9595/bootapp/sso/logout

    我按预期退出。

    BUT

    当我重新登录userA时,谁同时拥有(USER_MVC和USER_BOOT)角色,当我尝试访问时,我仍然可以看到main.jsp但是

    http://localhost:9595/mvcapp/
    

    Tomcat引发了403!即使userA具有所需的角色(USER_MVC)。

    顺便说一下:

    如果我打开新的隐身窗口,并使用userA 首先登录(不像之前那样使用userB登录),我可以访问bootapp和mvcapp,并在注销后再次登录使用userB(谁不应该访问mvcapp)我也可以访问bootapp和mvcapp。

    似乎我必须向mvcapp发送某种令牌或东西,但是什么?如何?但如果是这样,那么当用户A登录时,用户如何评估mvcapp? (我在所有认证的东西中都是新手)

    我已经有一段时间了,因为我一直试图找到解决方案,但我无法做到。请帮忙!

1 个答案:

答案 0 :(得分:0)

我将建议稍作更改。我不确定是什么问题。但是,您可以尝试这些并提供反馈。

尝试将您的密钥库客户端的“访问类型”更改为“机密”,将此设置用作“公共”

您的sso属性文件包括=>

keycloak.public-client=true

当您更改为“机密”时,必须像这样更改您的sso配置(这是针对启动应用程序。同样,您也需要针对mvc应用程序进行更改。)=>

keycloak.realm=IAP
keycloak.auth-server-url=http://10.60.6.34:8282/auth
keycloak.ssl-required=external
keycloak.resource=my_client
keycloak.principal-attribute=preferred_username
keycloak.credentials.secret= /* your client secret you will reach this under 
                               "instalation tab" of IAP client

尝试在服务器注销时删除“ JSESSIONID”,对于启动应用程序,您可以将此代码块添加到SecurityConfig类(配置方法)

.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)

=>

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests() 
    .....
    .....
    .and().logout().logoutUrl("*log out url*")
                        .clearAuthentication(true)
                        .deleteCookies("JSESSIONID")
                        .invalidateHttpSession(true)
    .....
    .....
}