首页 文章

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

提问于
浏览
0

使用Spring Boot(后端)和React(前端)进行开发时,我遇到了一个奇怪的行为 . React和Spring启动都在localhost:8080上运行 .

当我在localhost:8080上从React发送POST请求到Spring Boot时,我在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

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

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

使用软件POSTMAN发送POST请求时,我也没有错误 .

github:https://github.com/The-Taskmanager/SelfServiceWebwizard

The post request

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));

}

The mapping in 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 Security Config

@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

-- UPDATE --

我不明白,但似乎API ERROR与浏览器控制台上的访问有关!我从POST请求中删除了console.log方法,API ERROR消失了 .

这是我在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));
}

So does anybody know if there is a restriction on the browser's console and how to disable this?

2 回答

  • 0

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

  • 0

    由我自己解决 .

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

    Firefox给了我关于资源地址和401 ERORR的提示:
    enter image description here

    所以我在SecurityConfig中的configure(HttpSecurity http)中添加了 "/build/static/js/*.js" 到antMatchers:

    .antMatchers("/",
                        "/index",
                        "/index.html",
                        "/favicon.ico",
                        "/**/*.png",
                        "/**/*.gif",
                        "/**/*.svg",
                        "/**/*.jpg",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.map",
                        "/**/*.js",
                        "/build/static/js/*.js")
    

    如果你问我为什么这只发生在localhost:8080(在同一个原点),我想,主要的路径 . [...] . js是不同的 .

相关问题