인프런 커뮤니티 질문&답변

홍세호님의 프로필 이미지
홍세호

작성한 질문수

스프링 시큐리티 완전 정복 [6.x 개정판]

인트로

405에러가 발생합니다. 이유를 잘 모르겠습니다.

작성

·

446

1

1

package com.attendance.scheduler.infra.config.security;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig {

    public static final String[] ENDPOINTS_WHITELIST = {
            "/", "/submit", "/completion",
            "/class/**",
            "/board/**",
            "/join/**",
            "/cert/**",
            "/help/**",
            "/comment/**",
            "/css/**",
            "/js/**"
    };

    private final CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

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

    @Bean
    public SecurityFilterChain adminFilterChain(HttpSecurity httpSecurity) throws Exception {

        httpSecurity
                .csrf(AbstractHttpConfigurer::disable)
                .securityMatcher("/admin/**","/manage/**")
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/admin/**")
                        .hasAuthority("ADMIN")
                        .requestMatchers("/manage/**")
                        .hasAnyAuthority("ADMIN", "TEACHER")
                        .anyRequest().authenticated())

                .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer
                        .defaultSuccessUrl("/manage/class", true)
                        .failureHandler(customAuthenticationFailureHandler)
                        .loginPage("/login")
                        .loginProcessingUrl("/login")
                )

                .logout(httpSecurityFormLogoutConfigurer -> httpSecurityFormLogoutConfigurer
                        .logoutUrl("/logout")
                        .invalidateHttpSession(true)
                        .deleteCookies("JSESSIONID")
                        .logoutSuccessUrl("/"))

                .sessionManagement(sessionManagement -> sessionManagement
                        .invalidSessionUrl("/login")
                        .maximumSessions(1)
                        .maxSessionsPreventsLogin(true)
                        .expiredUrl("/login"));

        return httpSecurity.build();
    }
}

 

2

package com.attendance.scheduler.infra.config.security;

import com.attendance.scheduler.admin.domain.AdminEntity;
import com.attendance.scheduler.admin.repository.AdminJpaRepository;
import com.attendance.scheduler.infra.config.security.Admin.AdminDetails;
import com.attendance.scheduler.infra.config.security.User.TeacherDetails;
import com.attendance.scheduler.teacher.domain.TeacherEntity;
import com.attendance.scheduler.teacher.repository.TeacherJpaRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@RequiredArgsConstructor
public class AccountDetailService implements UserDetailsService {

    private final AdminJpaRepository adminJpaRepository;
    private final TeacherJpaRepository teacherJpaRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info("teacherId = {}", username);

        final TeacherEntity teacherEntity = teacherJpaRepository
                .findByUsernameIs(username);
        if(teacherEntity != null){
            
            return new TeacherDetails(teacherEntity);
            
        } else {
            final AdminEntity adminEntity = adminJpaRepository
                    .findByUsernameIs(username);
            if (adminEntity != null) {
                log.info("adminId = {}", username);
                return new AdminDetails(adminEntity);
            }
        }
        throw new UsernameNotFoundException(username);
    }
}

3

<form method='post' th:action="@{/login}" th:object="${login}">

 

로그인을 진행하면 405에러가 계속 발생합니다. 이유를 찾고 있으나 아이디와 비밀번호를 입력해도 2번 코드의 로그에 남지 않습니다. 혹시 이유를 알려주실수 있을까요? 감사합니다.

답변 2

0

정수원님의 프로필 이미지
정수원
지식공유자

@Bean
public SecurityFilterChain adminFilterChain(HttpSecurity httpSecurity) throws Exception {

    httpSecurity
            .csrf(AbstractHttpConfigurer::disable)
            .securityMatcher("/admin/**","/manage/**")

위 코드에서 .securityMatcher("/admin/**","/manage/**") 가 설정되어 있는데 이렇게 되면 /admin/** 와 /manage/** 경로로 접근하는 요청 이외에는 시큐리티 보안을 타지 않습니다.

그리고 현재

.formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer
        .defaultSuccessUrl("/manage/class", true)
        .failureHandler(customAuthenticationFailureHandler)
        .loginPage("/login")
        .loginProcessingUrl("/login")
        .permitAll() // 추가
)

폼 로그인 접근도 permitAll 이 되어 있지 않는데 이 부분도 인증받지 않는 상태에서도 접근이 가능하도록 해 주어야 합니다. 그렇지 않으면 무한 반복에 빠질 수 있습니다.

일단 위와 같이 설정하면 로그인은 되는데 403 으로 나오고 있습니다.

이것은 권한 문제인데 확인해 보시기 바랍니다.

홍세호님의 프로필 이미지
홍세호
질문자

해결했습니다. 알려주셔서 감사합니다!

0

정수원님의 프로필 이미지
정수원
지식공유자

전체 소스를 깃헙에 공유 부탁드립니다

홍세호님의 프로필 이미지
홍세호
질문자

홍세호님의 프로필 이미지
홍세호

작성한 질문수

질문하기