Метод 405 не разрешен, весенняя загрузка, но я использовал заголовок токена csrf

#java #amazon-web-services #spring-boot #csrf #http-status-code-405

#java #amazon-web-services #весенняя загрузка #csrf #http-status-code-405

Вопрос:

Я создаю сервер веб-приложений с весенней загрузкой. В первые дни разработки я использовал настройки http.csrf().disable() , и веб-страница работала хорошо. Но ошибки возникали ТОЛЬКО на странице адреса хоста с тех пор, как параметр отключения был удален. Когда я запросил GET , он работает абсолютно нормально, однако он не работает с POST, PUT, DELETE… Когда я тестирую на своем локальном хосте, все запросы работают, включая эти методы.

Я уже использовал заголовок токена csrf, скрытые входные данные csrf в формах и beforeSend которые устанавливают заголовок csrf в ajax. Я даже изменил настройку nginx ( error_page 405 =200 $uri; ), но она осталась прежней. Это моя среда.

jdk 11
spring 2.3.5
AWS EC2 — Amazon Linux 2 AMI
AWS RDS — PostgreSQL 13
AWS S3 Nginx 1.18.0
gradle 5.6.4
thymeleaf

Есть ли кто-нибудь, кто может мне помочь, пожалуйста?

Моя ссылка на репозиторий Github

 # aws server- nohup.out
[ec2-user@teamcoder-webservice ~]$ vim ~/app/step3/nohup.out
2020-12-01 23:24:18.953  INFO 3697 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3ad85136, org.springframework.security.web.context.SecurityContextPersistenceFilter@2bc426f0, org.springframework.security.web.header.HeaderWriterFilter@176f7f3b, org.springframework.security.web.csrf.CsrfFilter@7d3c09ec, org.springframework.security.web.authentication.logout.LogoutFilter@1f53481b, org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@7f93dd4e, org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter@5ad5be4a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@33425811, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@4cb2918c, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@737d100a, org.springframework.security.web.session.SessionManagementFilter@58740366, org.springframework.security.web.access.ExceptionTranslationFilter@4af45442, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@671c4166]
2020-12-01 23:24:20.068  INFO 3697 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2020-12-01 23:24:20.550  INFO 3697 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8081 (http) with context path ''
2020-12-01 23:24:20.552  INFO 3697 --- [           main] DeferredRepositoryInitializationListener : Triggering deferred initialization of Spring Data repositories…
2020-12-01 23:24:21.474  INFO 3697 --- [           main] DeferredRepositoryInitializationListener : Spring Data repositories initialized!
2020-12-01 23:24:21.499  INFO 3697 --- [           main] s.a.ScheduledAnnotationBeanPostProcessor : No TaskScheduler/ScheduledExecutorService bean found for scheduled processing
2020-12-01 23:24:21.527  INFO 3697 --- [           main] c.j.team.teamcoder.TeamCoderApplication  : Started TeamCoderApplication in 17.806 seconds (JVM running for 19.458)
2020-12-01 23:24:23.438  INFO 3697 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-12-01 23:24:23.443  INFO 3697 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-12-01 23:24:23.460  INFO 3697 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 17 ms
2020-12-02 03:05:22.223  WARN 3697 --- [nio-8081-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
 
 # /etc/nginx/nginx.conf

http {
...
 server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
        include /etc/nginx/conf.d/service-url.inc;

        location / {
                limit_except GET POST PUT DELETE {
                        deny all;
                }
                proxy_pass $service_url;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
        }
        error_page 405  =200 $uri;

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}
 
 #after change upper configuration

[ec2-user@teamcoder-webservice nginx]$ sudo /usr/sbin/nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
 

Кроме того, следующий код является кодом загрузки java spring.

 <!--ajax non-used request in "user_info.html"-->
<form th:action="@{'/api/v1/user/pic/'   ${user.id}}" method="post" enctype="multipart/form-data" name="pictureForm">
    <table>
        <tr><td><label th:for="picture">Profile Image</label></td>
            <td><input type="file" id="picture" name="picture" accept="image/png, image/jpeg" /></td></tr>
        <tr><td><img th:src="@{${user.picture}}" id="picture_img" alt="put your image"></td>
            <td><input type="button" name="Upload" value="Upload" onclick="submit_file_form(document.forms['pictureForm'].picture, 'pictureForm');" class="btn btn-info"/></td></tr>
    </table>
    <input type="hidden" name="pastPath" id="pastPath" th:value="${user.picture}"/>
    <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
</form>
 
 //ajax used request in "user_info.html" -> "userInfo.js"

...

const csrfToken = $('#_csrf').attr('content');
const csrfHeader = $('#_csrf_header').attr('content');


var user_info = {

    init : function () {
        var _this = this;

        $('#btn-update').on('click', function () {
            _this.update();
        }); 

        $('#btn-delete').on('click', function () {
            _this.delete();
        });
    },
    update : function () {
        var data = {
            name: $('#name').val(),
            tags: commaToArray(convertTags($('#tags').val())),
            email: $('#email').val(),
            birth: $('#birth').val(),
            education: $('#education').val().toUpperCase(),
            location: $('#location').val()
        };

        var id = $('#id').val();

        $.ajax({
            type: 'PUT', 
            url: '/api/v1/user/' id,
            dataType: 'json',
            contentType:'application/json; charset=utf-8',
            data: JSON.stringify(data),
            beforeSend: function (xhr){
                xhr.setRequestHeader(csrfHeader, csrfToken);
            }
        }).done(function() {
            alert('your information is modified');
            window.location.href = '/';
        }).fail(function (error) {
            alert(JSON.stringify(error));
        });
    },
...
 
 <!-- in html header -->

<meta id="_csrf" th:name="${_csrf.parameterName}" th:content="${_csrf.token}"/>
<meta id="_csrf_header" name="_csrf_header" th:content="${_csrf.headerName}"/>
 
 @RequiredArgsConstructor
@RestController
public class UserApiController {

    private  final UserService userService;
    private final RoleService roleService;

    @PutMapping("/api/v1/user/{id}")
    public Long update(@PathVariable String id,
                       @RequestBody UserUpdateRequestDto requestDto){

        roleService.reloadRolesForAuthenticatedUser(Role.USER.getKey());
        return userService.update(Long.valueOf(id), requestDto);
    }
}

@RequiredArgsConstructor
@RestController
public class FileController {

    private final UserService userService;]
    private final S3Service s3Service;

    @PostMapping("/api/v1/user/pic/{id}")
    public String updateUserPic(@PathVariable String id,
                                @RequestParam("pastPath") String pastPath,
                            @RequestPart("picture") MultipartFile multipartFile) throws IOException {

        String uploadDir = s3Service.upload(pastPath, multipartFile,"users/");
        userService.updatePic(Long.valueOf(id), uploadDir);

        return "You successfully uploaded "   uploadDir   "!";
    }
}
 
 //SecurityConfig.java

@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final CustomOAuth2UserService customOAuth2UserService;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**", "/js/**", "/assets/img/**", "/lib/**", "/user-photos/**", "/group-files/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and()
                .authorizeRequests()  
                .antMatchers("/", "/logoption","/user/denied", "/search/**", "/privacy/rule","/profile").permitAll()  
                .antMatchers("/api/v1/user/**", "/api/v1/**").hasRole("GUEST")
                .antMatchers("/api/v1/group/**", "/group/**", "/api/v1/participate/**").hasRole("USER") 
                .anyRequest().authenticated()   
            .and()
                .logout().logoutSuccessUrl("/")
                .deleteCookies("JSESSIONID")
                .invalidateHttpSession(true)
            .and()
                .exceptionHandling()
                .accessDeniedPage("/user/denied")
            .and()
                .oauth2Login()
                    .loginPage("/logoption")
                    .defaultSuccessUrl("/")
                    .userInfoEndpoint()// after oauth2 login
                        .userService(customOAuth2UserService); 

    }
    
    //for Spring Security
    @Bean
    public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
        return new ServletListenerRegistrationBean<>(new HttpSessionEventPublisher());
    }
}

 

Ответ №1:

Попробуйте добавить их в свой SecurityConfig :

 http.cors().and()....
 

И CORS config:

 @Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");  // TODO: lock down before deploying
    config.addAllowedHeader("*");
    config.addExposedHeader(HttpHeaders.AUTHORIZATION);
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}