Прошло несколько недель с тех пор, как я начал работать с весной, сейчас я пытаюсь расширить свои знания.То, что я пытаюсь сделать, это.
У меня есть приложение Spring MVC, которое использует Spring Security и имеет простую форму входа в систему, и после входа в систему некоторые простые операции CRUD, это работает хорошо, когда я вхожу в приложение, используя форму jsp.
но когда я выполняю аналогичное действие из ANGULAR-приложения, запрос не приземляется и возвращает код состояния 302, тогда делается другой запрос на страницу входа в приложение Spring и возвращается html-имя входа.
ниже приведены классы конфигурации, которые я использую:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired(required = true)
private UserDetailsService userDetailsService;
private static final String[] AUTH_WHITELIST = {
// -- swagger ui
"/swagger-resources/**", "/swagger-ui.html", "/v2/api-docs",
"/webjars/**", "/swagger.json", "/swagger*/**", "/user/**" };
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
};
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(
passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
web.ignoring().antMatchers("/v2/api-docs/**");
web.ignoring().antMatchers("/swagger.json");
web.ignoring().antMatchers("/swagger-ui.html");
web.ignoring().antMatchers("/swagger-resources/**");
web.ignoring().antMatchers("/webjars/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().authorizeRequests().antMatchers(AUTH_WHITELIST)
.authenticated().anyRequest().permitAll().and()
.authorizeRequests().anyRequest().hasAnyRole("ADMIN", "USER")
.and().authorizeRequests().antMatchers("/login**").permitAll()
.and().formLogin().loginPage("/login")
.loginProcessingUrl("/loginAction").permitAll().and().logout()
.logoutUrl("/logout")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login").permitAll()
.deleteCookies("JSESSIONID").invalidateHttpSession(true).and()
.csrf().disable();
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.maximumSessions(1).expiredUrl("/login.jsp");
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST",
"PUT", "DELETE", "PATCH"));
configuration.setAllowCredentials(false);
configuration.setAllowedHeaders(Arrays.asList("Authorization",
"Cache-Control", "Content-Type","X-Requested-With","Access-Control-Allow-Headers","Accept"));
configuration.addAllowedHeader("*");
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Другой класс конфигурации с именем WebConfig, который реализует WebMvcConfigurer
@Configuration
@PropertySource("classpath:documentation.properties")
@ComponentScans(value = {
@ComponentScan(basePackages = { "com.xx.xx.xx" }),
@ComponentScan("com.xx.xx.xx") })
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp().prefix("/WEB-INF/views/").suffix(".jsp");
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:4200")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("Authorization", "Cache-Control",
"Content-Type", "X-Requested-With",
"Access-Control-Allow-Headers")
.exposedHeaders("Cache-Control", "Content-Type")
.allowCredentials(false).maxAge(4800);
// Add more mappings...
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// Register resource handler for resources
registry.addResourceHandler("/resources/**")
.addResourceLocations("/WEB-INF/resources/")
.setCacheControl(
CacheControl.maxAge(2, TimeUnit.HOURS).cachePublic());
registry.addResourceHandler("swagger-ui.html").addResourceLocations(
"classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
И остальной API, я пытаюсьвызов из приложения ANGULAR.
@CrossOrigin(origins = "http://localhost:4200", maxAge = 4800, allowCredentials = "false")
@RestController
public class UserController {
private static final Class<UserController> className = UserController.class;
@Autowired
UserService userService;
@CrossOrigin
@PostMapping(value = "/user/authenticate")
@ApiOperation(value = "Authenticate User", notes = "${UserController.authenticate.notes}")
public void authenticate(
@ApiParam(value = "${UserController.authenticate.body}", required = true) @RequestBody String userData,
HttpServletResponse response) throws IOException {
System.out.println("called");
try {
String result = userService.authenticateUser(userData);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.getWriter().write(result);
} catch (JSONException e) {
System.out.println(e.getLocalizedMessage());
}
}
}
Я звоню, чтобы подтвердить подлинность API с телом POST.URL-адрес "http://localhost:8080/spring-security-example/user/authenticate". Теперь я буду делиться снимками экрана сетевого трафика при попытке входа в систему из углового приложения.
Экран 1: запрос Original First, но с запросомМетод ORIGIN
Экран 2: Второй запрос, который был отправлен автоматически с методом запроса GET, должен быть POST, я не знаю, где он был изменен
- Экран 3:первый запрос на вход в систему JSP, который также не был отправлен мной
- Экран 4: последний запрос, в котором вы можете увидеть код login.jsp вернул
Теперь, если я удаляю csrf().disable()
из HttpSecurity, у меня будет только два запроса на аутентификацию, сначала будет метод запроса ORIGIN, а следующим будет метод запроса POST, но он вернет 403, запрещенных как пружинный блок csrf.запросы, когда csrf включен.
Так что мой вопрос в том, что я делаю здесь неправильно,и почему метод запроса изменяется на GET сам по себе с csrf().disable()
.