早上好,我正在开发一个springboot(最新版本)应用程序,使用springsecurity(最新版本)进行保护。
我在试着做一个决定 PUT
从jsp页面向spring rest端点的请求,该端点只应返回 String
对象,尤其是:
jsp代码:在一个脚本中,我发出以下ajax请求
<!-- change event of batch status script -->
function changeEventStatus(idEvento, statoEvento) {
let data = {"id_evento": idEvento, "stato": statoEvento};
$.ajax({
url: 'http://localhost:8080/entsorgafin/events/api/cambiaStatoEvento',
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify(data)
}).then(function (data) {
console.log("process terminated.");
console.log("data collected:");
console.log(data);
});
}
控制器代码:控制器带有注解 @RestController
以及 @CrossOrigin
注解以支持cors请求和rest请求的spring自动管理
@PutMapping("/cambiaStatoEvento")
public String changeEventStatus(@RequestBody Evento evento)
{
logger.info("API CONTROLLER - changing the status of the event with ID " + evento.getId_evento());
//If the status status is not Risolto, the event will be taken in charge
if(! evento.getStato().equals("Risolto"))
{
logger.info("API CONTROLLER - status of event " + evento.getId_evento() + " changed to In Lavorazione");
eventoService.changeEventStatus(evento.getId_evento(), "In Lavorazione");
} else
{
logger.info("API CONTROLLER - status of event " + evento.getId_evento() + " changed to Risolto");
eventoService.changeEventStatus(evento.getId_evento(), "Risolto");
}
return "SUCCESS";
}
我使用chrome devtools进行了检查,有效负载被正确编码并发送,但是当我发出请求时,spring引导会记录以下内容:
2021-01-18 17:18:00.822 DEBUG 15564 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : "FORWARD" dispatch for PUT "/accessDenied", parameters={}
2021-01-18 17:18:00.827 WARN 15564 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'PUT' not supported]
2021-01-18 17:18:00.828 DEBUG 15564 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Exiting from "FORWARD" dispatch, status 405
2021-01-18 17:18:00.829 DEBUG 15564 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for PUT "/error", parameters={}
2021-01-18 17:18:00.830 DEBUG 15564 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2021-01-18 17:18:00.832 DEBUG 15564 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
2021-01-18 17:18:00.832 DEBUG 15564 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Writing [{timestamp=Mon Jan 18 17:18:00 CET 2021, status=405, error=Method Not Allowed, trace=org.springframe (truncated)...]
2021-01-18 17:18:00.833 DEBUG 15564 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 405
说到这里,我试着 GET
请求并按预期工作正常 DELETE
以及 POST
请求不起作用 PUT
一个。
仅仅通过阅读日志,我认为这是一个spring安全问题,但我不明白我面临的问题是什么,我从spring文档中看到cors请求是自动管理的,不应该做任何事情,但它显然不是这样工作的。
如果有人能帮我解决我所缺少的问题,或者只是指出一些我能找到答案的地方,因为我真的不知道这里会出什么问题,提前谢谢。
编辑
安全配置
package com.entsorgafin.sr002EagleCloud.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
//Dependency Injection
@Autowired
private PasswordEncoder passwordEncoder;
@Qualifier("securityUserDetailService")
@Autowired
private UserDetailsService userDetailsService;
/**
* Manages the encoder to save passwords in the DB
* not in plain text
*
* @return PasswordEncoder object
*/
@Bean
public PasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
/**
* Manages the configuration of the Authentication manager with
* user credentials and roles.
* <p>
* The AuthenticationManager processes any authentication request.
*
* @param auth AuthenticationManagerBuilder object
*/
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth)
{
auth.authenticationProvider(authenticationProvider());
}
/**
* Manages the configuration for specific http request.
*
* @param http HttpSecurity request
* @throws Exception exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
//configure security for pages
.antMatchers("/static/**").permitAll()
.antMatchers(new String[]{"/login", "/accessDenied"}).permitAll()
.antMatchers("/**").access("hasAnyRole('admin', 'operatore', 'ufficio tecnico', 'processista')")
.anyRequest().authenticated()
//creates login form
.and().formLogin().loginPage("/login").loginProcessingUrl("/login")
.defaultSuccessUrl("/home").failureUrl("/accessDenied")
.usernameParameter("id_utente").passwordParameter("password")
//catches exceptions http 403 response
.and().exceptionHandling().accessDeniedPage("/accessDenied");
http.requestCache().disable();
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
/**
* Manages the storage of user credentials inside database
*
* @return The authenticationProvider Object
*/
@Bean
public DaoAuthenticationProvider authenticationProvider()
{
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder);
return authenticationProvider;
}
@Bean
public AuthenticationTrustResolver getAuthenticationTrustResolver()
{
return new AuthenticationTrustResolverImpl();
}
}
关于 csrf
我在头部添加了jsp元标记 <sec:csrfMetaTags/>
它应该负责 csrf
保护或至少文件上说了这一点。
编辑2
通过如下更改ajax请求
<!-- change event of batch status script -->
function changeEventStatus(idEvento, statoEvento) {
let csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
let csrfToken = $("meta[name='_csrf']").attr("content");
let csrfHeader = $("meta[name='_csrf_header']").attr("content");
let data = {};
let headers = {};
data[csrfParameter] = csrfToken;
data["id_evento"] = idEvento;
data["stato"] = statoEvento;
headers[csrfHeader] = csrfToken;
$.ajax({
url: 'http://localhost:8080/entsorgafin/events/api/cambiaStatoEvento',
type: 'PUT',
headers: headers,
contentType: 'application/json',
data: JSON.stringify(data)
}).then(function (data) {
console.log("process terminated.");
console.log("data collected:");
console.log(data);
});
}
请求被正确执行,现在的问题是如何处理csrf令牌,因为spring试图反序列化并将其放入java对象( Evento
在这种情况下)和回馈
Failed to evaluate Jackson deserialization for type [[simple type, class com.entsorgafin.sr002EagleCloud.model.Evento]]
Could not resolve parameter [0] in public java.lang.String com.entsorgafin.sr002EagleCloud.controller.rest.EventsController_rest.changeEventStatus(com.entsorgafin.sr002EagleCloud.model.Evento): Content type 'application/json;charset=UTF-8' not supported
Completed 415 UNSUPPORTED_MEDIA_TYPE
请求的有效负载是:
{_csrf: "88c27418-7d48-4d76-a6ec-d76e7a45a61a", id_evento: 50, stato: "Attivo"}
如何指示spring boot不使用csrf令牌进行反序列化?
暂无答案!
目前还没有任何答案,快来回答吧!