在localhost:8080上的完全身份验证错误,但在localhost:3000

时间:2018-07-17 20:30:36

标签: spring reactjs spring-boot react-native http-post

在使用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

端口8080上的Firefox输出 Firefox Port 8080

当我将相同的POST请求从localhost:3000(React开发版本)发送到localhost:8080上的Spring Boot时,我没有错误!

Firefox在端口3000上的输出 enter image description here

使用软件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));
} 

那么,有人知道浏览器的控制台是否受到限制以及如何禁用此限制?

2 个答案:

答案 0 :(得分:0)

尝试在application.properties文件(例如server.port = 8081)中为spring添加新端口,然后尝试通过该端口访问

答案 1 :(得分:0)

自己解决。

由于受限制的控制台访问,但在受限制的React资源上,未发生API错误。实际上只有一个React资源受到限制: /static/js/main.RANDOM_CODE.js

Firefox给了我提示,带有资源地址和401 ERORR: enter image description here

因此,我已在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的路径是不同的。