【问题标题】:NullPointerException when getting username from principal从主体获取用户名时出现 NullPointerException
【发布时间】:2021-12-13 04:20:32
【问题描述】:

当我尝试在后端获取用户名时

@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 为空,但是为什么 - 我可以看到请求中有来自前端的 jwt 令牌?

【问题讨论】:

  • 如果从网络安全配置中删除 .antMatchers("/persons").permitAll() 会怎样?

标签: java spring spring-boot spring-security jwt


【解决方案1】:

调试到您的parseJwt(request) 以查看您的应用程序如何从请求中提取令牌。 access token 的做法是:它通常在 Authorization 标头中,并以 Bearer 开头

Request headers

Authorization: Bearer access-token

【讨论】:

    【解决方案2】:

    尝试像这样更改 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多