在使用Spring Boot(后端)和React(前端)进行开发时,我的行为很奇怪。 React和Spring boot都在localhost:8080上运行。
当我从React向Spring Boot在localhost:8080上发送POST请求时,我在Spring Boot中收到此错误:
2018-07-17 21:39:27.803 ERROR 8676 --- [nio-8080-exec-2] c.s.jwt.JwtAuthenticationEntryPoint : Responding with unauthorized error. Message - Full authentication is required to access this resource
当我将相同的POST请求从localhost:3000(React开发版本)发送到localhost:8080上的Spring Boot时,我没有错误!
使用软件POSTMAN发送POST请求时,我也没有错误。
github:https://github.com/The-Taskmanager/SelfServiceWebwizard
帖子请求
login(username: string, password: string) {
fetch('http://localhost:8080/api/auth/signin', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Accept': '*/*'
},
body: JSON.stringify({
"usernameOrEmail": username,
"password": password
})
}).then(response => {
console.log(response);
console.log("Authorization header console.log: " + response.headers.get("Authorization"));
let token = response.headers.get("Authorization");
this.setToken(token != null ? token : '');
}
).catch(error => console.error(error));
}
Spring Boot中的映射
@PostMapping("/signin")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsernameOrEmail(),
loginRequest.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.generateToken(authentication);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
headers.add("Authorization", new JwtAuthenticationResponse(jwt).getAccessToken());
return ResponseEntity.ok().headers(headers).build();
}
Spring Boot安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* Loads user related data .
*/
@Autowired
UserDetailsServiceImpl userDetailsService;
/**
* Handles exceptions from unauthorized access
*/
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
/**
* Returns new JwtAuthenticationFilter
*
* @return new JwtAuthenticationFilter
*/
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
/**
* Creates an authentication manager. Sets authentication menchanism.
*
* @param authenticationManagerBuilder authentication manager builder
* @throws Exception
*/
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
/**
* Authentication manager to authenticate a user
*
* @return
* @throws Exception
*/
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* Returns a bcrypt password encoder. Bcrypt is a hash function for passwords so the passwords are not saved in
* clear text.
*
* @return bcrypt password encoder
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* Creates protection rules for specific paths.
*
* @param http security type
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/",
"/index",
"/index.html",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/api/auth/**")
.permitAll()
.antMatchers("/api/auth/fetch")
.permitAll()
.antMatchers("/api/auth/signin")
.permitAll()
.antMatchers("/api/user/checkUsernameAvailability", "/api/user/checkEmailAvailability")
.permitAll()
.antMatchers(HttpMethod.GET, "/api/users/**")
.permitAll()
.anyRequest()
.authenticated();
// add own filters
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
/**
* Handles the cross-origin ressource sharing.
*
* @return CORS configuration
*/
@Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues();
source.registerCorsConfiguration("/**", config);
return source;
}
}
application.properties
# search path for static content (for react)
spring.resources.static-locations=file:build,classpath:/public,classpath:/static
# path to database file
spring.datasource.url=jdbc:h2:file:./data/h2db/h2_database;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
# database platform
spring.datasource.platform=h2
# data base drive
spring.datasource.driver-class-name=org.h2.Driver
# JSON web token secret
app.jwtSecret= fsiuhfsdihfdspsfdhspiufdhpvc
# 0.5 days
app.jwtExpirationInMs = 43200000
# activate to persist data, otherwise the data will be deleted on restart
# spring.jpa.hibernate.ddl-auto = update
-更新-
我不明白,但似乎API错误与浏览器控制台上的访问有关!我从POST请求中删除了console.log方法,并且API错误消失了。
这是我在React中的请求方法:
login(username: string, password: string) {
fetch('http://localhost:8080/api/auth/signin', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Accept': '*/*'
},
body: JSON.stringify({
"usernameOrEmail": username,
"password": password
})
}).then(response => {
console.log(response);
console.log("Authorization header console.log: " + response.headers.get("Authorization"));
let token = response.headers.get("Authorization");
this.setToken(token != null ? token : '');
}
).catch(error => console.error(error));
删除console.log方法:
login(username: string, password: string) {
fetch('http://localhost:8080/api/auth/signin', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Accept': '*/*'
},
body: JSON.stringify({
"usernameOrEmail": username,
"password": password
})
}).then(response => {
let token = response.headers.get("Authorization");
this.setToken(token != null ? token : '');
}
).catch(error => console.error(error));
}
那么,有人知道浏览器的控制台是否受到限制以及如何禁用此限制?
答案 0 :(得分:0)
尝试在application.properties文件(例如server.port = 8081)中为spring添加新端口,然后尝试通过该端口访问
答案 1 :(得分:0)
自己解决。
由于受限制的控制台访问,但在受限制的React资源上,未发生API错误。实际上只有一个React资源受到限制: /static/js/main.RANDOM_CODE.js
Firefox给了我提示,带有资源地址和401 ERORR:
因此,我已在SecurityConfig的configure(HttpSecurity http)的antMatchers中添加了“ / build / static / js / *。js” :
from django.db.models import Count
AchievementHistory.objects.filter(user=user).values('achievement__title').annotate(
Count('achievement__title')
).order_by()
如果您问我为什么这仅发生在localhost:8080(在同一来源)上,我想,通往main。[...]。js的路径是不同的。