java.lang.NullPointerException: Cannot invoke "java.security.Principal.getName()" because "principal" is null
at com.side_fpt.team_service.controller.VoteController.submitVote(VoteController.java:58)
요즘 팀원들과 사이드 프로젝트를 하고 있는데, 분명 로그인 되어있는데 Principal 정보를 못받아오는 것.
로그 확인해보니 principal이 null이라 getName()이 불가해서 나는 오류로 확인됨.
package com.side_fpt.team_service.security;
import com.side_fpt.team_service.util.constant.Privillages;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig {
private static final String[] WHITELIST = {
"/login",
"/register",
"/css/**",
"/fonts/**",
"/js/**",
"**",
"/check-email",
"/forgot-password",
"/reset-password",
"/change-password"
};
@Bean
public static PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers(WHITELIST).permitAll()
.requestMatchers("/admin/**").hasAnyRole("ADMIN", "EDITOR")
.requestMatchers("/admin/**").hasAuthority(Privillages.ACCESS_ADMIN_PANEL.getPrivillage()) // admin 페이지는 특정권한만 접근가능.
.anyRequest().authenticated()
)
// 이하 생략
WHITELIST로 설정란 루트 중에 "**" 전체소스를 표현하는 스트링이 들어가 있었다.
문제가 되는 Principal == null 이슈는 SecurityFilterChain 설정에서 너무 많은 경로를 permitAll()로 허용해서 인증 정보가 붙지 않기 때문으로 판단되어, 해당 "**"를 제거 후 실행하니 정상적으로 principal 정보가 들어오는 것으로 확인되었다.
💡 .permitAll() :
해당 요청 경로에 대해 Spring Security의 인증 필터를 통과시켜 로그인 없이도 접근 가능하게 해 줌.
💡 추가 정보
메서드 | 설명 |
.permitAll() | 인증 없이 접근 허용 |
.authenticated() | 인증된 사용자만 접근 허용 |
.hasRole("USER") | 특정 역할을 가진 사용자만 접근 허용 |
.denyAll() | 모든 사용자 접근 거부 |