NullPointerException при получении имени пользователя от принципала

0

Когда я пытаюсь получить имя пользователя на сервере

@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/persons")
public class PersonController {
...

@PostMapping
    public ResponseEntity<PersonDto> addPerson(@RequestBody PersonDto objectDto, @AuthenticationPrincipal Principal principal){
System.out.println(principal.getName());

Я получил ошибку

2021-10-27 23:30:39.309 ERROR 10744 --- [nio-8081-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

Я вижу, что фронтент отправляет токен JWT (не смотрите на accessToken, я добавил его в заголовок вручную).

POST /persons HTTP/1.1
Host: localhost:8081
Connection: keep-alive
Content-Length: 217
sec-ch-ua: "Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
accessToken: eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJHaWVuZWsiLCJpYXQiOjE2MzUzNjg1MjQsImV4cCI6MTYzNTQ1NDkyNH0.leuqnc-8fHNBVhTmukruom-RudxicWP3ykkMyMiapwY8bBVCFLwlNssXNK-gyo0RHig9d-dg83-QG9LDqVO9VA
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36
Content-Type: application/json
Accept: application/json, text/plain, */*
x-access-token: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJHaWVuZWsiLCJpYXQiOjE2MzUzNjg1MjQsImV4cCI6MTYzNTQ1NDkyNH0.leuqnc-8fHNBVhTmukruom-RudxicWP3ykkMyMiapwY8bBVCFLwlNssXNK-gyo0RHig9d-dg83-QG9LDqVO9VA
sec-ch-ua-platform: "Windows"
Origin: http://localhost:4200
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:4200/
Accept-Encoding: gzip, deflate, br
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7

По какой причине бэкенд его не видит?

Прикрепление конфигурации безопасности - дайте мне знать, если вам понадобится дополнительная информация

package pl.portal.randkowy.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.core.userdetails.UserDetailsService;

@Configuration
@EnableWebSecurity(debug=true)
@EnableGlobalMethodSecurity(
       // securedEnabled = true,
       // jsr250Enabled = true,
        prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsService userDetailsService;

    @Autowired
    private AuthEntryPointJwt unauthorizedHandler;

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().antMatchers("/api/auth/**").permitAll()
                .antMatchers("/api/test/**").permitAll()
                .antMatchers("/persons").permitAll()
                .antMatchers("/persons/**").permitAll()
                .antMatchers("/preferences/**").permitAll()
                .antMatchers("/interests/**").permitAll()
                .antMatchers("/secretdata/**").permitAll()
                .anyRequest().authenticated();

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }

}

Когда я пытаюсь это проверить

@PostMapping
    public ResponseEntity<PersonDto> addPerson(@RequestBody PersonDto objectDto, Principal principal){
        //zalogowany użytkownik
        Object principal2 = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        System.out.println("--------------------------------------*****************");
        if (principal2 instanceof UserDetailsImpl) {
            String username = ((UserDetailsImpl)principal2).getUsername();
            System.out.println(username);
        } else {
            String username = principal2.toString();
            System.out.println(username);
        }
        System.out.println("--------------------------------------*****************");

я получил

--------------------------------------*****************
anonymousUser
--------------------------------------*****************

Почему Spring Security не читает этот токен? Он отправляется во внешний интерфейс после процедуры входа в систему, так что все должно быть в порядке. Spring должен попасть в заголовок из этой опции x-access-token?

РЕДАКТИРОВАТЬ: во время отладки я обнаружил, что jwt имеет значение null, но почему - я вижу, что в запросе есть токен jwt из внешнего интерфейса?

jwt - ноль в запросе, jwt отображается

1
  • Что, если вы удалите .antMatchers ("/ people"). AllowedAll () из конфигурации веб-безопасности? 2 дня назад
0

Выполните отладку, parseJwt(request)чтобы увидеть, как ваше приложение извлекает токен из запроса. Практика access tokenтакова: обычно он находится в Authorizationзаголовке и начинается сBearer

Request headers

Authorization: Bearer access-token
0

попробуйте изменить webSecurityConfig следующим образом

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable()
            .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .authorizeRequests().antMatchers("/api/auth/**").permitAll()
            .antMatchers("/api/test/**").permitAll()
            .antMatchers("/persons/**").permitAll()
            .antMatchers("/preferences/**").permitAll()
            .antMatchers("/interests/**").permitAll()
            .antMatchers("/secretdata/**").permitAll()
            .anyRequest().authenticated();

    http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
Новый участник
swabih is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.