首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >标头内容.在axios中定义的类型

标头内容.在axios中定义的类型
EN

Stack Overflow用户
提问于 2022-02-21 22:31:54
回答 1查看 1.1K关注 0票数 1

在将我的登录前端逻辑(Vue3 + Axios)集成到Java (与Spring安全)上时,我遇到了一些小麻烦。

我得到了以下错误:

代码语言:javascript
运行
复制
com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
 at [Source: (org.apache.catalina.connector.CoyoteInputStream); line: 1, column: 0]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4344) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4189) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3242) ~[jackson-databind-2.10.2.jar:2.10.2]
    at br.com.preferencialsaude.app.JWTLoginFilter.attemptAuthentication(JWTLoginFilter.java:35) ~[classes/:na]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]

在调试过程中,我发现我的HttpServletRequest中没有“Content: application/json”标题,但问题是,我实际上在axios客户端中将其设置为。

当我向邮递员发出请求时,它工作得很好,但是当我试图从我的前端应用程序中发出请求时,我得到了前面的错误。

我以为可能是浏览器,但在任何浏览器中都会出现同样的错误。我甚至尝试使用JS粪API提出请求,但行为仍然相同。

当我从浏览器发出请求时,MimeHeaderFields:

代码语言:javascript
运行
复制
host, connection, accept, access-control-request-method, access-control-request-headers,
origin,user-agent, sec-fetch-mode, sec-fetch-site, sec-fetch-dest, referer,
accept-encoding, accept-language

正如你所看到的,没有Content-Type,但是当我向邮递员提出请求时,它是存在的。

这是我的客户端代码:

代码语言:javascript
运行
复制
async handleSubmit () {
    const response = await axios.post('http://localhost:8080/ws/login',
      { username: this.login, password: this.senha }, { 
        headers: { 
          'Content-Type': 'application/json',
        }
      });

    console.log(response.data)
    localStorage.setItem('token', response.data.token);
}

下面是我的后端Java过滤器:

代码语言:javascript
运行
复制
import java.io.IOException;
import java.util.Collections;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.fasterxml.jackson.databind.ObjectMapper;

import br.com.preferencialsaude.app.model.AccountCredentials;
import br.com.preferencialsaude.app.service.TokenAuthenticationService;

public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {

    protected JWTLoginFilter(String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {

        //here is where I get the error, due to the lack of Content-Type header
        AccountCredentials credentials = new ObjectMapper().readValue(request.getInputStream(), AccountCredentials.class);

        UsernamePasswordAuthenticationToken userAuthData =
            new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword(), Collections.emptyList());

        return getAuthenticationManager().authenticate(userAuthData);
    }

这就是我在邮递员中得到的结果:

代码语言:javascript
运行
复制
{"token":"eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0aGFseXMiLCJleHAiOjE2NDYzMzM2OTB9.5wYyYs6jwhIsxob99Ubx4b64jIIMjVKXf0bZ_ZS_zhkPtrK0KOgKxOgy0HgxlEdV_F5DTwOeDooqVRouEuAqEA"}

使用status代码200

这是我的WebSecurityConfig课程:

代码语言:javascript
运行
复制
package br.com.preferencialsaude.app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import br.com.preferencialsaude.app.service.MyUserDetailsService;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    
    private MyUserDetailsService userDetailsService;
    
    public WebSecurityConfig(MyUserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }
    
    public BCryptPasswordEncoder passwordEncoder() {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        return bCryptPasswordEncoder;
    }
    
    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
            .antMatchers("/", "/login").permitAll()
            .antMatchers(HttpMethod.POST, "/ws/login").permitAll()
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(new JWTLoginFilter("/ws/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
            .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .formLogin()
                .loginPage("/login")
                .failureUrl("/login?error=true")
                .defaultSuccessUrl("/gerenciador/home", true)
                .usernameParameter("usuario")
                .passwordParameter("senha")
                .and()
            .logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/gerenciador/logout"))
                .logoutSuccessUrl("/gerenciador/login").and().exceptionHandling()
                .accessDeniedPage("/error");
    }
    
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
           "/resources/**", "/static/**", "/css/**", "/js/**", "/imagens/**",
            "/webfonts/**", "/jasper/**", "/contratos/**",
            "/v2/api-docs", "/swagger-resources/**", "/configuration/ui", "/swagger-ui.html", "/webjars/**",
            "/procedimento/**", "/procedimento/**/**", "/credenciamento/empresa/**", "/credenciamento/pessoa/**",
            "/credenciamento/farmacia/**", "/buscaCep", "/plano/**", "/contrato/empresa/**",
            "/contrato/pessoa-fisica/**", "/rede-credenciada/**", "/ws/rede-credenciada/**", "/ws/endereco/**",
            "/ws/procedimentos/**", "/ws/recuperar-senha/**", "/api/cupons-venda/**", "/atendimento/**",
            "/termos", "/convenio/**", "/ws/agendamento/**", "/ws/consulta/**", "/ws/notificacoes/**", "/ws/avaliacao/**",
            "/ws/imagens/**", "/actuator/**", "/api/enderecos/**", "/api/cadastros-clientes/**", "/api/cidades/**",
            "/api/planos/**", "/api/especialidades-saude/consultas/**", "/api/rede-atendimento/**"
        );
    }
}

这是我的JWTLoginFilter:

代码语言:javascript
运行
复制
package br.com.preferencialsaude.app;

import java.io.IOException;
import java.util.Collections;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.fasterxml.jackson.databind.ObjectMapper;

import br.com.preferencialsaude.app.model.AccountCredentials;
import br.com.preferencialsaude.app.service.TokenAuthenticationService;

public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {

    protected JWTLoginFilter(String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {

        AccountCredentials credentials = new ObjectMapper().readValue(request.getInputStream(), AccountCredentials.class);

        UsernamePasswordAuthenticationToken userAuthData =
            new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword(), Collections.emptyList());

        return getAuthenticationManager().authenticate(userAuthData);
    }
    
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                            FilterChain filterChain, Authentication auth) throws IOException, ServletException {
        TokenAuthenticationService.addAuthentication(response, auth.getName());
    }
    
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException failed) throws IOException, ServletException {
        SecurityContextHolder.clearContext();
        TokenAuthenticationService.failAuthentication(response);
    }
}

你曾经遇到过类似的问题吗?我很感激你的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-23 19:01:42

我想出了如何通过在我的WebSecurityConfig文件中添加一些CORS配置来解决这个问题。

问题不在于内容类型头,而是阻止选项请求的Security。

这是我为解决这个问题而添加的代码。

代码语言:javascript
运行
复制
@Bean
public FilterRegistrationBean processCorsFilter() {     
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.setAllowedOrigins(Arrays.asList("http://localhost:8080", "http://localhost:8081",
                "https://site.preferencialsaude.com.br", "https://site-hmlg.preferencialsaude.com.br"));
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/ws/login", config);
    source.registerCorsConfiguration("/api/**", config);


    final FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return bean;
}

在本CORS配置教程中的注释中找到此代码:https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

如果您想接受来自所有来源的请求,只需替换setAllowedOrigins() with addAllowedOrigin("*"),因为我配置它的方式,如上面的代码所示,我不能从postman或任何其他来源登录,除非我定义了这些来源。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71213788

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档