使用OAuth2分离JHipster中的前端和API服务器不起作用 [英] Separating the front-end and the API server in JHipster with OAuth2 does not work

查看:0
本文介绍了使用OAuth2分离JHipster中的前端和API服务器不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用OAuth2创建了一个简单的JHipster 6.2.0角度应用程序,我还单独生成了一个客户端应用程序。此外,我还使用keyloak.yml为Keyloak创建了一个停靠器 这是JHipster附带的,但为作为数据库的PostgreSQL提供了更多参数。

在同一上下文中运行两个应用程序,默认情况下,一切正常。

为了在不同的上下文中运行这两个应用程序,如https://www.jhipster.tech/separating-front-end-and-api/所述,我在客户端的webpack.Common.js中设置了SERVER_API_URL='http://localhost:8080'

在此场景中,在dev模式下:

  1. 我在IDE(IntelliJ)中启动后端应用程序
  2. 我执行NPM START启动客户端
  3. 在Chrome浏览器中,我调用http://localhost:9000
  4. 单击"登录"链接
  5. 使用管理员凭据填充密钥罩的登录窗口
我没有收到一个带有文本‘您是以用户"admin"身份登录的窗口。’,而是再次返回到同一个主页,带有"Sign in"链接。因此我无法完成登录过程。

在此场景中,我从未到达Account资源上的API/Account方法公共UserDTO getAccount(主体主体)。在Chrome Network选项卡中,我看到两个帐户呼叫,状态代码均为302 OK。

如有任何解决此问题的想法,我们将不胜感激。

api/account call image

cmd

curl "http://localhost:8080/api/account" -H "Referer: http://localhost:9000/" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" --compressed

.yo-rc.json前端

{
  "generator-jhipster": {
    "promptValues": {
      "nativeLanguage": "es"
    },
    "jhipsterVersion": "6.2.0",
    "applicationType": "monolith",
    "baseName": "clientlauncher",
    "useSass": true,
    "clientPackageManager": "npm",
    "clientFramework": "angularX",
    "clientTheme": "none",
    "clientThemeVariant": "",
    "authenticationType": "oauth2",
    "cacheProvider": "no",
    "databaseType": "postgres",
    "devDatabaseType": "postgres",
    "prodDatabaseType": "postgres",
    "testFrameworks": [],
    "jhiPrefix": "jhi",
    "entitySuffix": "",
    "dtoSuffix": "DTO",
    "otherModules": [],
    "enableTranslation": true,
    "nativeLanguage": "es",
    "languages": ["es", "en"],
    "blueprints": [],
    "skipServer": true
  }
}

.yo-rc.json后端

{
  "generator-jhipster": {
    "promptValues": {
      "packageName": "com.xxx.yyy",
      "nativeLanguage": "es"
    },
    "jhipsterVersion": "6.2.0",
    "applicationType": "monolith",
    "baseName": "smartoee",
    "packageName": "com.xxx.yyy",
    "packageFolder": "com/xxx/yyy",
    "serverPort": "8080",
    "authenticationType": "oauth2",
    "cacheProvider": "ehcache",
    "enableHibernateCache": true,
    "websocket": false,
    "databaseType": "sql",
    "devDatabaseType": "postgresql",
    "prodDatabaseType": "postgresql",
    "searchEngine": false,
    "messageBroker": false,
    "serviceDiscoveryType": false,
    "buildTool": "maven",
    "enableSwaggerCodegen": false,
    "useSass": true,
    "clientPackageManager": "npm",
    "clientFramework": "angularX",
    "clientTheme": "none",
    "clientThemeVariant": "",
    "testFrameworks": [],
    "jhiPrefix": "jhi",
    "entitySuffix": "",
    "dtoSuffix": "DTO",
    "otherModules": [],
    "enableTranslation": true,
    "nativeLanguage": "es",
    "languages": ["es", "en"],
    "blueprints": []
  }
}

应用程序的安全性.yml

  security:
    oauth2:
      client:
        provider:
          oidc:
            issuer-uri: http://192.168.0.159:9080/auth/realms/jhipster
        registration:
          oidc:
            client-id: web_app
            client-secret: web_app

应用程序中的CORS-dev.yml:

  cors:
    allowed-origins: '*'
    allowed-methods: '*'
    allowed-headers: '*'
    exposed-headers: 'Authorization,Link,X-Total-Count'
    allow-credentials: true
    max-age: 1800   

I also tried, but it didn't work:   
  cors:
    allowed-origins:
      - http://localhost:8080
      - http://localhost:9000
      - http://localhost:9060
      - http://127.0.0.1:8080
      - http://127.0.0.1:9000
      - http://127.0.0.1:9060
      - http://192.168.0.159:9080
    allowed-methods: '*'
    allowed-headers: '*'
    exposed-headers: 'Authorization,Link,X-Total-Count'
    allow-credentials: true
    max-age: 1800

WebConfigurer.java中的CorsFilter:

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = jHipsterProperties.getCors();
        if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) {
            log.debug("Registering CORS filter");
            source.registerCorsConfiguration("/api/**", config);
            source.registerCorsConfiguration("/management/**", config);
            source.registerCorsConfiguration("/v2/api-docs", config);
        }
        return new CorsFilter(source);
    }

SecurityConfiguration.java中的配置

    @Override
    public void configure(WebSecurity web) {
        web.ignoring()
            .antMatchers(HttpMethod.OPTIONS, "/**")
            .antMatchers("/app/**/*.{js,html}")
            .antMatchers("/i18n/**")
            .antMatchers("/content/**")
            .antMatchers("/swagger-ui/index.html")
            .antMatchers("/test/**");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        .and()
            .addFilterBefore(corsFilter, CsrfFilter.class)
            .exceptionHandling()
            .accessDeniedHandler(problemSupport)
        .and()
            .headers()
            .contentSecurityPolicy("default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com data:")
        .and()
            .referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)
        .and()
            .featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none'")
        .and()
            .frameOptions()
            .deny()
        .and()
            .authorizeRequests()
            .antMatchers("/api/auth-info").permitAll()
            .antMatchers("/api/**").authenticated()
            .antMatchers("/management/health").permitAll()
            .antMatchers("/management/info").permitAll()
            .antMatchers("/management/prometheus").permitAll()
            .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .and()
            .oauth2Login()
        .and()
            .oauth2ResourceServer()
                .jwt()
                .jwtAuthenticationConverter(jwtAuthorityExtractor)
                .and()
            .and()
                .oauth2Client();
        // @formatter:on
    }

webpack.Common.js(客户端应用程序)

       new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: `'${options.env}'`,
                BUILD_TIMESTAMP: `'${new Date().getTime()}'`,
                VERSION: `'${packageJson.version}'`,
                DEBUG_INFO_ENABLED: options.env === 'development',
                // The root URL for API calls, ending with a '/' - for example: `"https://www.jhipster.tech:8081/myservice/"`.
                // If this URL is left empty (""), then it will be relative to the current context.
                // If you use an API server, in `prod` mode, you will need to enable CORS
                // (see the `jhipster.cors` common JHipster property in the `application-*.yml` configurations)
                SERVER_API_URL: `'http://localhost:8080/'`
            }
        }),

推荐答案

正如@MattRaible所说,问题是在这个角度客户机上没有真正了解OAuth的逻辑。因此,基本上,您应该遵循以下步骤来解决问题:

  • 安装Keyloak节点模块并在angular.js、webpack.Common.js和index.html几个文件中将其激活
  • 添加密钥罩服务以与密钥罩服务器交互
  • 添加拦截器以将我们的授权令牌放在每个http请求上
  • 稍作更改即可调整LogoutResource.java。

您可以在Github repo中找到此解决方案的示例。您还可以详细说明here

这篇关于使用OAuth2分离JHipster中的前端和API服务器不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆