I'm trying jhipster with token-based authentication. It works perfectly.
我正在尝试使用基于标记的身份验证。它的工作原理。
Now, I want to run back-end and front-end code on different domains. How can I do this?
现在,我想在不同的域上运行后端和前端代码。我该怎么做呢?
This is what I tried:
这就是我所尝试的:
-
Run
yo jhipster
and select token-based authentication option:运行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
-
Make two copies of the project as
jhipster/backend
andjhipster/frontend
将该项目复制为jhipster/后端和jhipster/frontend。
-
Delete unnecessary files from back-end and front-end
从后端和前端删除不必要的文件。
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
-
Make changes in code to completely remove backend/frontend dependency
在代码中进行更改,以完全消除后端/前端依赖性。
-
frontend/Gruntfile.js
前端/ Gruntfile.js
... var parseVersionFromPomXml = function() { return '1.2.2.RELEASE'; }; ... browserSync: { ..., proxy: "localhost:8081" }
-
frontend/src/main/webapp/scripts/app/app.js
前端/ src / main / webapp /脚本/ app / app.js
angular.module('jhipsterApp', [...]) .constant('API_URL', 'http://localhost:8080/') .run( ... )
-
frontend/src/main/webapp/scripts/**/*.service.js
前端/ src / main / webapp /脚本/ * * / * .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
后端/ pom.xml
Remove yeoman-maven-plugin
删除yeoman-maven-plugin
-
backend/src/main/java/com/mycompany/myapp/SimpleCORSFilter.java
后端java /com/mycompany/myapp/SimpleCORSFilter.java / src / main /
// 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", "*"); ... } }
-
-
Run
运行
-
Terminal Tab #1: BACKEND
终端标签# 1:后端
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 ----------------------------------------------------------
-
Terminal Tab #2: FRONTEND
终端标签# 2:前端
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
-
Terminal Tab #3: GRUNT
终端标签# 3:咕哝
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 -------------------------------------
-
-
Browse http://localhost:3000/#/login
浏览http://localhost:3000 / # /登录
Enter
username:password
asadmin:admin
管理员输入用户名:密码:admin
Our BACKEND tab reads:
我们的后台选项卡上写着:
[DEBUG] com.mycompany.myapp.security.Http401UnauthorizedEntryPoint - Pre-authenticated entry point called. Rejecting access
Apparently, I'm doing something wrong. What is it?
显然,我做错了什么。它是什么?
3 个解决方案
#1
9
When requests fail due to CORS, there is no visible error on the backend. The HTTP request actually succeeds, but is blocked on the front-end side by javascript. A message like this one will appear in the JS console.
当请求由于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.
The error message you're seeing is actually related to authentication. When you enable CORS, your JS will send ''pre-flight'' requests using the HTTP OPTIONS method. JHipster isn't configured to allow the OPTIONS method globally. I ran into this exact same problem myself while doing the same thing you did. The fix is very simple: just add this line to your com.mycompany.config.SecurityConfiguration
immediately preceding (before) the first antMatchers
entry.
您所看到的错误消息实际上与身份验证有关。当您启用CORS时,您的JS将使用HTTP选项方法发送“预飞行”请求。JHipster没有被配置为允许全局选择方法。在做同样的事情时,我自己也遇到了同样的问题。修复非常简单:只需将这一行添加到您的com.mycompany.config中。在第一个antMatchers条目之前(before)之前的SecurityConfiguration。
.antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/api/**").permitAll()
This will explicitly allow all requests with the OPTIONS method. The OPTIONS method is used in CORS as a way to read all of the headers and see what HTTP methods are allowed in the CORS request.
这将显式地允许使用选项方法的所有请求。在CORS中使用选项方法来读取所有的头信息,并查看在CORS请求中允许使用什么HTTP方法。
Finally, in your SimpleCORSFilter class, you should also add these headers:
最后,在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");
#2
0
You can use CORS filter from Tomcat put dependency in pom.xml
:
您可以使用Tomcat的CORS过滤器,将依赖项放在pom.xml中:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>8.0.15</version>
<scope>provided</scope>
</dependency>
Use whatever version of Tomcat you use.
使用任何版本的Tomcat。
Add CORS filter initialization in WebConfigurer
:
在WebConfigurer中添加CORS filter初始化:
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);
}
put this line in WebConfigurer.onStartup(...)
put it as close to the top as possible.
把这条线放在WebConfigurer.onStartup(…)上,把它放在尽可能靠近顶部的位置。
...
initCorsFilter(servletContext, disps);
...
#3
0
In addition to xeorem's answer above, I also had to modify the parse-links-service.js to handle the preflight OPTIONS responses, which don't have the "link" response header:
除了以上xeorem的答案,我还必须修改parse-links-service。js处理的preflight选项响应,没有“链接”响应头:
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(',');
...
Instead of adding API_URL to app.js, modify Gruntfile.js and add the API_URL to the ngConstants block for both DEV and PROD environments.
而不是在app.js中添加API_URL,修改Gruntfile。在DEV和PROD环境中,将API_URL添加到ngConstants块中。
#1
9
When requests fail due to CORS, there is no visible error on the backend. The HTTP request actually succeeds, but is blocked on the front-end side by javascript. A message like this one will appear in the JS console.
当请求由于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.
The error message you're seeing is actually related to authentication. When you enable CORS, your JS will send ''pre-flight'' requests using the HTTP OPTIONS method. JHipster isn't configured to allow the OPTIONS method globally. I ran into this exact same problem myself while doing the same thing you did. The fix is very simple: just add this line to your com.mycompany.config.SecurityConfiguration
immediately preceding (before) the first antMatchers
entry.
您所看到的错误消息实际上与身份验证有关。当您启用CORS时,您的JS将使用HTTP选项方法发送“预飞行”请求。JHipster没有被配置为允许全局选择方法。在做同样的事情时,我自己也遇到了同样的问题。修复非常简单:只需将这一行添加到您的com.mycompany.config中。在第一个antMatchers条目之前(before)之前的SecurityConfiguration。
.antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/api/**").permitAll()
This will explicitly allow all requests with the OPTIONS method. The OPTIONS method is used in CORS as a way to read all of the headers and see what HTTP methods are allowed in the CORS request.
这将显式地允许使用选项方法的所有请求。在CORS中使用选项方法来读取所有的头信息,并查看在CORS请求中允许使用什么HTTP方法。
Finally, in your SimpleCORSFilter class, you should also add these headers:
最后,在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");
#2
0
You can use CORS filter from Tomcat put dependency in pom.xml
:
您可以使用Tomcat的CORS过滤器,将依赖项放在pom.xml中:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>8.0.15</version>
<scope>provided</scope>
</dependency>
Use whatever version of Tomcat you use.
使用任何版本的Tomcat。
Add CORS filter initialization in WebConfigurer
:
在WebConfigurer中添加CORS filter初始化:
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);
}
put this line in WebConfigurer.onStartup(...)
put it as close to the top as possible.
把这条线放在WebConfigurer.onStartup(…)上,把它放在尽可能靠近顶部的位置。
...
initCorsFilter(servletContext, disps);
...
#3
0
In addition to xeorem's answer above, I also had to modify the parse-links-service.js to handle the preflight OPTIONS responses, which don't have the "link" response header:
除了以上xeorem的答案,我还必须修改parse-links-service。js处理的preflight选项响应,没有“链接”响应头:
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(',');
...
Instead of adding API_URL to app.js, modify Gruntfile.js and add the API_URL to the ngConstants block for both DEV and PROD environments.
而不是在app.js中添加API_URL,修改Gruntfile。在DEV和PROD环境中,将API_URL添加到ngConstants块中。