将jhipster后端和前端分成两个项目?

时间:2015-03-13 09:07:18

标签: java angularjs authentication jwt jhipster

我正在尝试jhipster基于令牌的身份验证。它运作得很好。

现在,我想在不同的域上运行后端和前端代码。我怎么能这样做?


这就是我的尝试:

  1. 运行yo jhipster并选择基于令牌的身份验证选项:

    Welcome to the JHipster Generator
    
    ? (1/13) What is the base name of your application? jhipster
    ? (2/13) What is your default Java package name? com.mycompany.myapp
    ? (3/13) Do you want to use Java 8? Yes (use Java 8)
    ? (4/13) Which *type* of authentication would you like to use? Token-based authentication (stateless, with a token)
    ? (5/13) Which *type* of database would you like to use? SQL (H2, MySQL, PostgreSQL)
    ? (6/13) Which *production* database would you like to use? MySQL
    ? (7/13) Which *development* database would you like to use? H2 in-memory with Web console
    ? (8/13) Do you want to use Hibernate 2nd level cache? Yes, with ehcache (local cache, for a single node)
    ? (9/13) Do you want to use clustered HTTP sessions? No
    ? (10/13) Do you want to use WebSockets? No
    ? (11/13) Would you like to use Maven or Gradle for building the backend? Maven (recommended)
    ? (12/13) Would you like to use Grunt or Gulp.js for building the frontend? Grunt (recommended)
    ? (13/13) Would you like to use the Compass CSS Authoring Framework? No
    
    ...
    
    I'm all done. Running bower install & npm install for you
    ^C
    
  2. 将项目的两个副本设为jhipster/backendjhipster/frontend

  3. 从后端和前端删除不必要的文件

    rm -rf backend/.bowerrc
    rm -rf backend/.jshintrc
    rm -rf backend/bower.json
    rm -rf backend/Gruntfile.js
    rm -rf backend/package.json
    rm -rf backend/src/main/webapp
    rm -rf backend/src/test/javascript
    
    rm -rf frontend/pom.xml
    rm -rf frontend/src/main/java
    rm -rf frontend/src/main/resources
    rm -rf frontend/src/test/gatling
    rm -rf frontend/src/test/java
    rm -rf frontend/src/test/resources
    
  4. 在代码中进行更改以完全删除后端/前端依赖

    • frontend/Gruntfile.js

      ...
      var parseVersionFromPomXml = function() {
          return '1.2.2.RELEASE';
      };
      ...
      browserSync: { ..., proxy: "localhost:8081" }
      
    • frontend/src/main/webapp/scripts/app/app.js

      angular.module('jhipsterApp', [...])
      .constant('API_URL', 'http://localhost:8080/')
      .run( ... )
      
    • frontend/src/main/webapp/scripts/**/*.service.js

      angular.module('jhipsterApp').factory(..., API_URL) {
          return $http.post(API_URL + 'api/authenticate', ...);
      }
      
      angular.module('jhipsterApp').factory('Account', function Account($resource, API_URL) {
          return $resource(API_URL + 'api/account', {}, {...});
      }
      
      // Make similar changes in all service files.
      
    • backend/pom.xml

      删除yeoman-maven-plugin

    • backend/src/main/java/com/mycompany/myapp/SimpleCORSFilter.java

      // Copied from here: https://spring.io/guides/gs/rest-service-cors/
      
      @Component
      public class SimpleCORSFilter implements Filter {
          public void doFilter(...) {
              ...
              response.setHeader("Access-Control-Allow-Origin", "*");
              ...
          }
      }
      
  5. 生成

    • 终端标签#1: BACKEND

      cd backend
      mvn spring-boot:run
      
      ...
      [INFO] com.mycompany.myapp.Application - Started Application in 11.529 seconds (JVM running for 12.079)
      [INFO] com.mycompany.myapp.Application - Access URLs:
      ----------------------------------------------------------
              Local:          http://127.0.0.1:8080
              External:       http://192.168.56.1:8080
      ----------------------------------------------------------
      
    • 终端标签#2: FRONTEND

      cd frontend/src/main/webapp
      npm install -g http-server
      http-server
      
      Starting up http-server, serving ./ on: http://0.0.0.0:8081
      Hit CTRL-C to stop the server
      
    • 终端标签#3: GRUNT

      cd frontend
      bower install
      npm install
      grunt serve
      
      ...
      [BS] Proxying: http://localhost:8081
      [BS] Access URLs:
       -------------------------------------
             Local: http://localhost:3000
          External: http://10.34.16.128:3000
       -------------------------------------
                UI: http://localhost:3001
       UI External: http://10.34.16.128:3001
       -------------------------------------
      
  6. 浏览http://localhost:3000/#/login

    输入username:password作为admin:admin

    我们的 BACKEND 标签显示为:

    [DEBUG] com.mycompany.myapp.security.Http401UnauthorizedEntryPoint - Pre-authenticated entry point called. Rejecting access
    

  7. 显然,我做错了什么。它是什么?

5 个答案:

答案 0 :(得分:9)

当请求因CORS而失败时,后端没有可见错误。 HTTP请求实际上成功,但是在前端被javascript阻止。像这样的消息将出现在JS控制台中。

XMLHttpRequest cannot load http://localhost:8080/api/authenticate. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access.

您看到的错误消息实际上与身份验证有关。当您启用CORS时,您的JS将发送“飞行前”''''使用HTTP OPTIONS方法的请求。 JHipster未配置为全局允许OPTIONS方法。我在做同样的事情时遇到了同样的问题。修复非常简单:只需将此行添加到第一个com.mycompany.config.SecurityConfiguration条目之前(之前)的antMatchers

.antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/api/**").permitAll()

这将明确允许使用OPTIONS方法的所有请求。 OPTIONS方法在CORS中用作读取所有标头的方法,并查看CORS请求中允许的HTTP方法。

最后,在SimpleCORSFilter类中,您还应添加以下标题:

response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "86400"); // 24 Hours
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, x-auth-token");

答案 1 :(得分:1)

除了上面的xeorem的答案之外,我还必须修改parse-links-service.js来处理预检OPTIONS响应,它们没有"链接"响应标题:

var links = {};
if (!angular.isObject()) {
    // CORS OPTIONS responses
    return links;
}

if (header.length == 0) {
    throw new Error("input must not be of zero length");
}

// Split parts by comma
var parts = header.split(','); 

...

不是将API_URL添加到app.js,而是修改Gruntfile.js并将API_URL添加到DEV和PROD环境的ngConstants块中。

答案 2 :(得分:0)

您可以使用Tomcat中的CORS过滤器将依赖项放在pom.xml

   <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-catalina</artifactId>
        <version>8.0.15</version>
        <scope>provided</scope>
    </dependency>

使用您使用的任何版本的Tomcat。

WebConfigurer中添加CORS过滤器初始化:

private void initCorsFilter(ServletContext servletContext, EnumSet<DispatcherType> disps) {
        log.debug("Registering CORS Filter");
        FilterRegistration.Dynamic corsFilter = servletContext.addFilter("corsFilter", new CorsFilter());
        Map<String, String> parameters = new HashMap<>();
        parameters.put("cors.allowed.headers", "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization");
        parameters.put("cors.allowed.methods", "GET,POST,HEAD,OPTIONS,PUT,DELETE");
        corsFilter.setInitParameters(parameters);
        corsFilter.addMappingForUrlPatterns(disps, false, "/*");
        corsFilter.setAsyncSupported(true);
    }

将此行放在WebConfigurer.onStartup(...)中,尽可能靠近顶部。

...
initCorsFilter(servletContext, disps);
...

答案 3 :(得分:0)

我正在使用Jhipster版本4.14.5

  • 我已将以下文件复制到Project-forntend文件夹:

    .bowerrc
    吞咽
    pom.xml
    yarn.lock
       gulpfile.js
    readme.md

    bower_components
    .gitattributes
        src / main / web

    bower.json
    .gitignore
    package.json
        target / www

  • 然后运行:

    纱线安装

    下安装

    gulp安装

  • 然后将gulp / config.js文件更改为:

    apiPort:8081

    uri:'http://localhost:'

  • 然后通过运行以下命令启动项目:

    大口服务

答案 4 :(得分:0)

在JHipster应用程序中分离前端和后端非常简单。如果要使用JHipster分别设置前端和后端应用程序,请按照以下步骤操作:

  1. 为前端和后端应用程序创建两个目录

    • mkdir前端
    • mkdir后端
  2. 将目录更改为前端并运行JHipster命令以仅创建前端模块

    • cd前端
    • jhipster --skip-server --db = sql --auth = jwt
    • 如果一切正常,请运行 {{ Form::open(array( 'method' => 'POST', 'class' => 'form-horizontal form-label-left', 'route' => ['edit_settings'], 'id' => 'editSettingsForm', 'files' => true, 'novalidate' => true)) }} <div class="col-md-12 col-sm-12 col-xs-12"> @foreach($configList as $key => $cl) <div class="item form-group"> @php $caption = $cl['config_key']; $caption = str_replace('_', ' ', $caption); @endphp <label class="control-label col-md-3 col-sm-3 col-xs-12" for="config_key">@if($caption == 'emails'){{ 'Admin ' . ucfirst($caption) }}@else{{ ucfirst($caption) }}@endif <span class="required">*</span> </label> <div class="col-md-9 col-sm-9 col-xs-12"> {{ Form::hidden('config_key[]', $cl['config_key'], array( 'id' => 'config_key_' . $key, 'class' => 'form-control col-md-7 col-xs-12', 'data-validate-length-range' => '3,50', 'placeholder' => 'Config Key', 'required' => 'required' )) }} @if($cl['value_unit'] == 'date') {{ Form::select('config_value[]', array( 'd-m-Y' => 'd-m-Y', 'd/m/Y' => 'd/m/Y', 'd.m.Y' => 'd.m.Y', 'Y-m-d' => 'Y-m-d', 'Y/m/d' => 'Y/m/d', 'Y.m.d' => 'Y.m.d', 'm-d-Y' => 'm-d-Y', 'm/d/Y' => 'm/d/Y', 'm-d-Y' => 'm.d.Y' ), $cl['config_value'], array( 'class' => 'form-control col-md-7 col-xs-12', 'id' => 'config_value_' . $key )) }} @elseif($cl['value_unit'] == 'time') {{ Form::select('config_value[]', array( 'H:i:s' => 'H:i:s', 'H.i.s' => 'H.i.s', 'H:i' => 'H:i', 'H.i' => 'H.i', 'h:i:s A' => 'h:i:s A', 'h.i.s A' => 'h.i.s A', 'h:i:s a' => 'h:i:s a', 'h.i.s a' => 'h.i.s a', 'h:i A' => 'h:i A', 'h.i A' => 'h.i A', 'h:i a' => 'h:i a', 'h.i a' => 'h.i a' ), $cl['config_value'], array( 'class' => 'form-control col-md-7 col-xs-12', 'id' => 'config_value_' . $key )) }} @elseif($cl['value_unit'] == 'url') {{ Form::url('config_value[]', $cl['config_value'], array( 'id' => 'config_value_' . $key, 'class' => 'form-control col-md-7 col-xs-12', 'data-validate-length-range' => '3,50', 'placeholder' => 'Config value', 'required' => 'required' )) }} @else {{ Form::text('config_value[]', $cl['config_value'], array( 'id' => 'config_value_' . $key, 'class' => 'form-control col-md-7 col-xs-12', 'data-validate-length-range' => '3,50', 'placeholder' => 'Config value', 'required' => 'required' )) }} @endif </div> </div> @endforeach <div class="ln_solid"></div> <div class="form-group"> <div class="col-md-6 col-md-offset-3"> <a class="btn btn-primary back_new" href="{{url('/cpanel/dashboard/')}}">Back</a> <button id="send" type="submit" class="btn btn-success submit_new">Submit</button> </div> </div> </div> <div style="clear:both;"></div> {{ Form::close() }} 命令以运行您的前端应用程序。
      

    我将mysql用于数据库,将JWT用于身份验证,如果要使用websocket,请添加:“ --websocket = spring-websocket”

  3. 现在,将目录更改为后端,然后运行JHipster命令以仅创建后端模块

    • cd .. //由于我们当前正在访问后端目录
    • cd后端
    • jhipster --skip-client
    • 在运行Spring Boot应用程序时运行后端应用程序

现在,您的前端和后端应用程序正在单独运行,并且前端通过REST API调用与后端应用程序进行协调。