- 이전에 작성한 구성 정보를 가지고
spring security
적용하여 메뉴별CRUD
권한 체크와 로그인 사용자의 접근 가능한 메뉴정보를 가져오는 기능을 작성해 보려 합니다. 이를 통해 가지고 있는 권한에 맞는 메뉴와CRUD
권한별 인가 설정을 할 수 있게 되었습니다.
spring security config 설정
spring security config
설정 정보 입니다.securityFilterChain()
메소드 안에 들어가있는 메소드 들은 의존주입 받은httpSecurity
를 이용하여 각 메소드별로 별개의 설정을 하게 하여 메소드명만으로도 구성정보를 쉽게 알아볼 수 있게 하였습니다.- 이번 포스팅에서는
securityFilterChain()
안에있는 구성 정보중authenticationProviderConfig()
구성만 살펴보겠습니다.
- 이번 포스팅에서는
@EnableMethodSecurity
를 적용하여 컨트롤러(메소드)별로 접근 권한을 설정하게 하였습니다.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
@Slf4j @Configuration @EnableMethodSecurity @RequiredArgsConstructor public class WebSecurityConfig { private final HttpSecurity httpSecurity; @Bean public SecurityFilterChain securityFilterChain() throws Exception { corsConfig(); csrfConfig(); headerConfig(); authorizeHttpRequestsConfig(); formLoginConfig(); oAuth2LoginConfig(); logOutConfig(); exceptionHandlingConfig(); authenticationProviderConfig(); return httpSecurity.build(); } }
User
User
엔티티 클래스 입니다. 로그인한 사용자의 정보를 해당 엔티티로 구성하여 인증 공급자를 거쳐SecurityContextHodler
안에서 관리되게 됩니다. 로그인한 유저의 메뉴별 CURD 권한 리스트와, 메뉴 리스트를 포함하고 있습니다.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
@Getter @ToString @NoArgsConstructor public class User implements UserDetails { private String userId; private String password; private String userType; private List<BackOfficeMenu> userMenuAuthorityList; private List<BackOfficeMenuRes> userMenuAuthorityResList; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return userMenuAuthorityList.stream() .map(BackOfficeMenu::getMenuAuthorityId) .map(SimpleGrantedAuthority::new) .toList(); } public void loginUserMenuList(List<BackOfficeMenuRes> backOfficeMenuRes){ this.userMenuAuthorityResList = backOfficeMenuRes; } ... }
getAuthorities()
부분에서 가져온BackOfficeMenu
에서 메뉴 권한 부분을 권한 리스트로 설정해줍니다. 작성하다 느낀건데BackOfficeMenu
클래스의 이름이 마음에 안드는군요. todo 목록으로 해당 클래스명을BackOfficeMenuAuthority
로 변경한다. 라고 기록후 넘어가겠습니다.
mybatis
코드 입니다. 쿼리된 결과를User
엔티티에 매핑시켜줍니다.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
<resultMap id="user" type="User"> <result property="userId" column="userId"/> <result property="password" column="password"/> <result property="userType" column="userType"/> <collection property="userMenuAuthorityList" ofType="BackOfficeMenu"> <result property="menuAuthorityId" column="menuAuthorityId"/> <result property="menuId" column="menuId"/> <result property="name" column="name"/> <result property="depth" column="depth"/> <result property="reference" column="reference"/> <result property="menuOrder" column="menuOrder"/> <result property="createDate" column="createDate"/> <result property="createId" column="createId"/> <result property="updateDate" column="updateDate"/> <result property="updateId" column="updateId"/> </collection> </resultMap> <sql id="selectUserInfoBasicSql"> SELECT b.menu_authority_id AS "menuAuthorityId", e.user_id AS "userId", e.password AS "password", e.user_type AS "userType", d.menu_id AS "menuId", d.name AS "name", d.depth AS "depth", d.reference AS "reference", d.menu_order AS "menuOrder", d.create_date AS "createDate", d.create_id AS "createId", d.update_date AS "updateDate", d.update_id AS "updateId" FROM common_code a INNER JOIN user_type_menu_authority b ON b.common_code_id = a.common_code_id INNER JOIN menu_authority c ON b.menu_authority_id = c.menu_authority_id INNER JOIN menu d ON d.menu_id = c.menu_id INNER JOIN "user" e ON e.user_type = a.common_code_id WHERE 1 = 1 </sql> <select id="selectUserByUserIdAndPassword" resultMap="user"> <include refid="selectUserInfoBasicSql"/> AND e.user_id = #{userId} AND e.password = #{password} </select> <select id="selectUserByUserId" resultMap="user"> <include refid="selectUserInfoBasicSql"/> AND e.user_id = #{userId} </select>
mybatis
의resultMap
이 의도한대로User
엔티티에 바인딩이 되는지 간단한 테스트를 통해 직관해 보도록 하겠습니다.@MybatisTest
를 이용하여 매퍼 테스트를 진행하였고 나머지 설명은 생략하겠습니다.ObjectMapper
의 경우 전체 스프링Bean
을 끌어오는게 아니라 주입이 되지 않아 직접 생성하여 사용하였습니다. 객체를 생성하여 테스트 하던 중에ObjectMapper
에서LocalDateTime
의 형변환이 안되어 추가적으로@BeforeEach
에서 형변환이 가능하게 해주는 모듈을 추가 설정 해주었습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
@Slf4j @MybatisTest @ActiveProfiles("local") @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class UserMapperTest { @Autowired private UserMapper userMapper; private final ObjectMapper objectMapper = new ObjectMapper(); @BeforeEach void setup() { objectMapper.registerModule(new JavaTimeModule()); } @Test void selectUserByUser() throws Exception { Optional<User> admin = userMapper.selectUserByUserIdAndPassword("ad_sub_admin", "1234"); Assertions.assertTrue(admin.isPresent()); User user = admin.get(); Assertions.assertNotNull(user); log.info("user info = {}", objectMapper.writeValueAsString(user)); } }
- 유저 정보를
JSON
형태로 출력하였고 아래는 그 결과입니다.
- 유저 정보를
- 다음 포스팅에서는
AuthenticationProvider
구성과 그 이후 설정들을 작성해보겠습니다.