가자공부하러!

Spring Security 활용 회원 관리 (1) - 개요, 환경설정, DB 모델링 본문

공부/Spring Boot

Spring Security 활용 회원 관리 (1) - 개요, 환경설정, DB 모델링

오피스엑소더스 2019. 9. 16. 18:03
소스코드 :
참고 : https://ryudung.tistory.com/20
참고 : http://progtrend.blogspot.com/2018/07/spring-boot-security.html
참고 : https://a1010100z.tistory.com/entry/Spring-Spring-security-%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EC%9E%90-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85%EB%B6%80%ED%84%B0-%EB%A1%9C%EA%B7%B8%EC%9D%B8%EA%B9%8C%EC%A7%80-Spring-boot-Gradle-MyBatis-MySQL
참고 :


1. Spring Security 개요

2. 환경설정

3. DB 모델링
4. 문제 해결




1. Spring Security 개요


1. 기본 동작 방식
  > 서블릿의 필터와 인터셉터를 이용
- 필터 : 스프링과 무관한 서블릿 자원
- 인터셉터 : 스프링의 빈으로 관리되면서 스프링의 컨텍스트 내에 속함
  > Spring Security Filter Chain의 필터들
- CharacterEncodingFilter : 요청에 대한 문자 인코딩을 지정할 수 있도록 해주는 서블릿 필터
- HiddenHttpMethodFilter : 게시 된 메소드 매개 변수를 HTTP 메소드로 변환하는 필터로, HttpServletRequest.getMethod()를 통해 검색할 수 있다.
- HttpPutFormContentFilter : HTTP PUT 또는 PATCH 요청 중에 ServletRequest.getParameter*() 패밀리 메소드를 통해 양식 인코딩 데이터를 사용할 수 있게 해주는 필터.
- RequestContextFilter : LocaleContextHolder 및 RequestContextHolder를 개입시켜, 현재의 thread에 요구를 공개하는 Servlet 필터

2. 인증과 인가
  > 인증(Authentication)
- 접근 주체가 누구인가에 대한 증명
- ex) 로그인
  > 인가(Authorization)
- 접근 주체가 특정 서비스나 페이지에 접근 권한이 있는가에 대한 증명
- ex) 관리자 페이지 접근 권한이 있는지 검사
- ex) USERNAME에 맞는 권한들을 AUTHORITIES 테이블에서 List 타입으로 가져온다
  > Spring Security에서의 인증과 인가
- AuthenticationManager : 인증 담당
- ProviderManager : 인증에 대한 처리를 AuthenticationProvide라는 타입의 객체를 이용해서 처리를 위임
- DaoAuthenticationProvider
- CasAuthenticationProvider
- LdapAuthenticationProvider
- RemoteAuthenticationProvider
- 위 AuthenticationProvider들은 실제 인증 작업을 수행한다.
- UserDetailsService : AuthenticationProvider가 전달한 권한에 대한 정보를 처리해서 반환해 준다.




2. 환경설정


1. 개발환경 :

  > spring boot 2.1.7(Maven, JSP, Tiles)

  > jdk 8

  > sts3


2. 설정 순서

  > 기본 환경 설정

- pom.xml 작성

- config 파일 작성 : src/main/java/com/exam/app/config/

- MyBatis mapper 작성 : src/main/resources/mapper/

- application.yml 작성 : src/main/resources/

- 컨트롤러 작성 : src/main/java/com/exam/app/common/controller/

  > DB 테이블 생성

- SEC_MEMBER, SEC_AUTHORITY

  > WebSecurityConfigurerAdapter를 상속받는 파일 작성

  > AuthenticationProvider 구현


3. 책 내용 참고

  > 소스코드 : https://github.com/HyeongJunMin/springboot/tree/master/SecurityExamWithBook

  > 기본 환경 설정

- pom.xml 작성

- config 파일 작성 : src/main/java/com/exam/app/config/

- MyBatis mapper 작성 : src/main/resources/mapper/

- application.yml 작성 : src/main/resources/

- 컨트롤러 작성 : src/main/java/com/exam/app/common/controller/

- URI 설계

- /exam/all : 모든 사용자 접근 가능

- /exam/member : 멤버만 접근 가능

- /exam/admin : 관리자 권한이 있는 사용자만 접근 가능

  > DB 테이블 생성

- SEC_MEMBER, SEC_AUTHORITY


  > AuthenticationSuccessHandler를 구현하는 파일 작성

- src/main/java/com/exam/app/config/CustomLoginSuccessHandler.java

- 로그인 처리를 수행하기 위함 

  > AbstractSecurityWebApplicationInitializer를 상속받는 파일 작성

- src/main/java/com/exam/app/config/SecurityInitializer.java

- DelegatingFilterProxy를 스프링에 등록하는 설정 

  > WebSecurityConfigurerAdapter를 상속받는 파일 작성

- src/main/java/com/exam/app/config/SpringSecurityConfiguration.java

- security-context.xml 역할을 수행

- @EnableWebSecurity : 스프링MVC와 스프링 시큐리티를 결합하기 위함

- 오버라이드 메소드

- void configure(HttpSecurity http)

- URI 별 필요한 권한 설정

- 로그인 관련 기능 설정

- 커스텀 로그인 폼, 로그인 성공 핸들러

- void configure(AuthenticationManagerBuilder auth)

- 테스트를 위한 기본 계정의 ID/PW와 권한 설정

- DB계정정보를 가져올 쿼리 설정

- queryUser : 계정이 있는지에 대한 여부를 검사

- queryDetails : 계정이 가진 권한이 무엇인지에 대해 검사

- 계정정보를 DB에서 가져오는 UserDetailsService를 활용해서 계정 인증/인가 수행

  > UserDetailsService를 구현하는 파일 작성

- src/main/java/com/exam/app/security/CustomUserDetailsService.java

- DB에서 인증, 인가 정보를 가져올 수 있는 mapper를 가짐

- UserDetails loadUserByUsername(String userName)

- 매개변수로 아이디를 받아서 mapper에서 찾은 후 UserDetails를 리턴

  > UserDetails를 구현하는 User를 상속받는 파일 작성

- src/main/java/com/exam/app/security/domain/CustomUser.java

-


  > AbstractAnnotationConfigDispatcherServletInitializer를 상속받는 파일 작성

- src/main/java/com/exam/app/config/WebConfig.java

  > AuthenticationSuccessHandler를 상속받는 파일 작성

- src/main/java/com/exam/app/security/CustomLoginSuccessHandler.java

- 로그인을 정상적으로 성공한 경우 수행할 내용을 설정


4. 완료내용 :

  > 커스텀 로그인 페이지 활용

  > URI 별 권한 설정

  > DB에 저장된 계정 정보를 통해 권한 부여(id, pw, enabled, authority)

  > 패키지 구조

├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─exam
│  │  │          │  SecurityExamWithBookApplication.java
│  │  │          │  ServletInitializer.java
│  │  │          ├─app
│  │  │          │  ├─common
│  │  │          │  │  ├─controller
│  │  │          │  │  │      LoginController.java
│  │  │          │  │  │      TestController.java
│  │  │          │  │  ├─dao
│  │  │          │  │  │      CommonDAO.java
│  │  │          │  │  └─model
│  │  │          │  │          AuthDTO.java
│  │  │          │  │          TestDTO.java
│  │  │          │  ├─config
│  │  │          │  │  ├─db
│  │  │          │  │  │      MariaDBConfiguration.java
│  │  │          │  │  └─security
│  │  │          │  │          RootConfig.java
│  │  │          │  │          SecurityInitializer.java
│  │  │          │  │          SpringSecurityConfiguration.java
│  │  │          │  │          WebConfig.java
│  │  │          │  └─security
│  │  │          │      │  CustomLoginSuccessHandler.java
│  │  │          │      │  CustomLogoutSuccessHandler.java
│  │  │          │      │  CustomUserDetailsService.java
│  │  │          │      └─domain
│  │  │          │              CustomUser.java
│  │  │          └─test
│  │  ├─resources
│  │  │  │  application.yml
│  │  │  ├─mapper
│  │  │  │  └─common
│  │  │  │          dbmapper.xml
│  │  │  │          TestDTOMapper.xml
│  │  │  ├─static
│  │  │  └─templates
│  │  └─webapp
│  │      └─WEB-INF
│  │          └─views
│  │              │  clogin.jsp
│  │              │  clogout.jsp
│  │              │  welcome.jsp
│  │              ├─admin
│  │              │      main.jsp
│  │              └─member
│  │                      main.jsp




****실패한 내용****

  > 테이블과 매핑되는 클래스와 매퍼 작성

- UserDetails를 구현하는 클래스 작성

- src/main/java/com/sse/app/member/model/Account.java

- 쿼리문을 저장할 매퍼 작성

- src/main/java/com/sse/app/member/model/AccountMapper.java

  > DAO 역할을 수행할 AccountRepository 작성

- src/main/java/com/sse/app/member/dao/AccountRepository.java

  > UserDetailsService를 구현하는 AccountService 작성

- src/main/java/com/sse/app/member/service/AccountService.java


****실패한 내용****

  > AuthenticationProvider 구현

- src/main/java/com/sse/app/config/MemberAuthenticationProvider.java

  > WebSecurityConfigurerAdapter를 상속받는 Configuration 파일 작성

- src/main/java/com/sse/app/config/WebSecurityConfig.java

  > 사용자 정보를 담는 인터페이스 UserDetails 구현

- src/main/java/com/sse/app/member/model/MemberUserDetails.java

- VO역할 수행

- 작성 내용

- 테이블이 갖는 컬럼에 맞게끔 멤버변수 작성 : id, pw, name, email, auth

- Collection<? extends GrantedAuthority> getAuthorities() : 계정이 갖고 있는 권한을 목록으로 리턴하기 위한 메소드 설정

- boolean isEnabled() : 계정의 활성/비활성 여부가 담긴 ENABLED멤버변수를 리턴

  > DB에서 유저 정보를 가져오기 위한 MemberDAO, xml 작성

- src/main/java/com/sse/app/member/dao/MemberDAO.java

- src/main/resources/mapper/member/Member.xml

  > 인증 절차 인터페이스 UserDetailsService 구현

- 추상화 해놓은 UserDetailsService를 상속받아 loadUserByName(String id)메소드를 구현

- loadUserByName(String id) : 유저의 id를 통해 유저에 대한 인증 정보를 가져오는 기능 수행

- 유저 id를 통해 해당 유저를 찾는 로직과 유저의 권한들을 가져오는 로직이 포함되어 있음

- 작성 내용

- loadUserByName(String id)

- 사용자 정보를 MemberUserDetails 타입으로 가져옴

- id에 해당하는 사용자 정보가 없으면 UsernameNotFoundException을 throw

- 사용자 정보가 있는 경우 user 리턴







3. DB 모델링


1
2
3
4
5
6
7
8
9
10
11
12
13
--기본적인 인증에 필요한 속성만 담은 테스트용 테이블
--is로 시작하는 컬럼은 spring security가 제공하는 검사 타입
CREATE TABLE SEC_MEMBER(
    USERNAME VARCHAR2(1000PRIMARY KEY,
    PASSWORD VARCHAR2(1000),
    isEnabled NUMBER(10)
);
 
--각 유저별로 할당되는 권한을 보관하는 테이블
CREATE TABLE SEC_AUTHORITY(
    USERNAME VARCHAR2(1000PRIMARY KEY,
    AUTHORITY_NAME VARCHAR2(1000)
);
cs


4. 문제 해결


1. Spring Security 기본 제공 폼 로그인 방법


Username에 user입력

password에 아래처럼 생성된 패스워드 입력




2. UserDetailsService 관련

  > 위치 : src/main/java/com/exam/app/config/SpringSecurityConfiguration.java

- 문제 : configure메소드에서 auth.jdbcAuthentication()...으로 db정보 꺼내오는 방법을 UserDetailsService 구현을 통해 꺼내오려고 시도할 때 문제 발생

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    log.info("configure............................");
    
    //테스트를 위한 기본 멤버 설정
//        auth
//            .inMemoryAuthentication()
//                .withUser("admin").password("{noop}admin").roles("ADMIN");
//        auth
//            .inMemoryAuthentication()
//                .withUser("member").password("{noop}member").roles("MEMBER");
//        
//        String queryUser = "SELECT ID, PW, ENABLED FROM MEMBER_TEST WHERE ID=?";
//        String queryDetails = "SELECT ID, AUTH FROM AUTH_TEST WHERE ID=?";
//        
//        auth
//            .jdbcAuthentication()
//                .dataSource(dataSource)
//                .passwordEncoder(pwe)
//                .usersByUsernameQuery(queryUser)
//                .authoritiesByUsernameQuery(queryDetails);
    auth.userDetailsService(customUserService()).passwordEncoder(pwe);
}
cs


- 오류내용

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
org.springframework.security.authentication.InternalAuthenticationServiceException: Cannot pass null or empty values to constructor
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:123) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:144) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:175) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:200) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) [spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_211]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_211]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.24.jar:9.0.24]
    at java.lang.Thread.run(Unknown Source) [na:1.8.0_211]
Caused by: java.lang.IllegalArgumentException: Cannot pass null or empty values to constructor
    at org.springframework.security.core.userdetails.User.<init>(User.java:113) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.core.userdetails.User.<init>(User.java:86) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at com.exam.app.security.domain.CustomUser.<init>(CustomUser.java:27) ~[classes/:na]
    at com.exam.app.security.CustomUserDetailsService.loadUserByUsername(CustomUserDetailsService.java:32) ~[classes/:na]
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:108) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    ... 57 common frames omitted
 
cs


- 해결 :

- 원인 : mapper xml에 컬럼이름지정이 잘못되어있어서 생성자 매개변수에 null이 들어갔음

- 해결방법 : 매퍼에 컬럼이름 수정, Spring Security가 기본적으로 다루는 변수명에 맞게 alias 지정(userid, userpw)


3. URI 별 권한설정 미인식

  > 문제 :

- /member/admin 리퀘스트는 ROLE_ADMIN 인가정보가 있어야만 접근이 가능한데, 없어도 접근이 되는 상태

- 소스코드( src/main/java/com/rhymes/app/config/security/SpringSecurityConfigutaion.java)

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
@Override
protected void configure(HttpSecurity http) throws Exception {
    // TODO Auto-generated method stub
super.configure(http);
log.info("HttpSecurity");
 
//URI패턴 별 권한 설정
http
    .authorizeRequests()
        .antMatchers("/welcome").permitAll()
        .antMatchers("/member/admin""/member/admin/**").access("hasRole('ROLE_ADMIN')")
        .antMatchers("/member/member""/member/member/**").access("hasRole('ROLE_MEMBER')");
//로그인페이지 설정
http
    .formLogin()
        .loginPage("/member/login").permitAll()
        .loginProcessingUrl("/login")
        .successHandler( loginSuccessHandler() );
 
//로그아웃 관련 설정
http
    .logout()
        .logoutUrl("/logout")
        .invalidateHttpSession(true)
        .deleteCookies("remember-me""JSESSION_ID")
            .logoutSuccessHandler(logoutSuccessHandler());
    
}
cs


  > 해결 방법

- 혹시나 싶어서 super.config(http);부분을 지워보니 정상적으로 403에러페이지 확인





Comments