기록
JAVA SPRING 시큐리티 연습 본문
먼저 테이블 만들기
CREATE TABLE MEM(
USER_NO NUMBER,
USER_ID VARCHAR2(50),
USER_PW VARCHAR2(100),
USER_NAME VARCHAR2(300),
COIN NUMBER,
REG_DATE DATE,
UPD_DATE DATE,
ENABLED VARCHAR2(1),
CONSTRAINT PK_MEM PRIMARY KEY(USER_NO)
);
CREATE TABLE MEM_AUTH(
USER_NO NUMBER,
AUTH VARCHAR2(50),
CONSTRAINT PK_MEM_AUTH PRIMARY KEY(USER_NO, AUTH),
CONSTRAINT FK_MEM_AUTH FOREIGN KEY(USER_NO) REFERENCES MEM(USER_NO)
);
mem테이블 (1)
mem_auth테이블(N)
SELECT A.USER_NO, A.USER_ID, A.USER_PW, A.USER_NAME, A.COIN, A.REG_DATE, A.UPD_DATE, A.ENABLED,
B.USER_NO, B.AUTH
FROM MEM A LEFT OUTER JOIN MEM_AUTH B
ON(A.USER_NO = B.USER_NO)
WHERE A.USER_ID = 'member1';
security-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- customAccessDenied를 자바빈(객체)으로 등록함/ 권한불일치시 다음의 클래스로 이동 -->
<bean id="customAccessDenied" class="kr.or.ddit.security.CustomAccessDeniedHandler"></bean>
<!-- 로그인 성공시 다음의 클래스로 이동 -->
<bean id="customLoginSuccess" class="kr.or.ddit.security.CustomLoginSuccessHandler"></bean>
<!-- 사용자가 정의한 비밀번호 암호화 처리기를 빈으로 등록함 -->
<bean id="customPassswordEncoder" class="kr.or.ddit.security.CustomNoOpPasswordEncoder"></bean>
<!-- 스프링 시큐리티에서 제공하는 BCryptPasswordEncoder 클래스를 자바빈으로 등록함 -->
<!-- <bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean> -->
<!-- 사용자정의 사용자 상세 기능 **** 중요-->
<bean id="customUserDetailsService" class="kr.or.ddit.security.CustomUserDetailsService"></bean>
<bean id="CustomLogoutSuccessHandler" class="kr.or.ddit.security.CustomLogoutSuccessHandler"></bean>
<!-- xmlns : xml namespace의 약자
Role : 권한(authorization)
permitAll : 누구나 접근 가능
hasRole : 권한을 갖은가인가?
-->
<security:http>
<!-- URI 패턴으로 접근 제한을 설정 -->
<security:intercept-url pattern="/board/list" access="permitAll"/>
<security:intercept-url pattern="/board/register" access="hasRole('ROLE_MEMBER')"/>
<security:intercept-url pattern="/notice/list" access="permitAll"/>
<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')"/>
<!-- 폼 기반 인증 기능을 사용 -->
<!-- 접근 제한에 걸리면 시큐리티가 기본적으로 제공하는 로그인 페이지로 이동 -->
<!-- <security:form-login/> -->
<!-- 사용자가 정의한 로그인 페이지의 URI를 지정함 -->
<security:form-login login-page="/login"
authentication-success-handler-ref="customLoginSuccess"/>
<!-- 로그인이 된 회원중에 권한이 없을때.. -->
<!-- 접근(access) 거부(denied) 처리자(handler)의 URI를 지정 -->
<!-- <security:access-denied-handler error-page="/accessError"/> -->
<!-- 등록한 CustomAccessDeniedHandler를 접근 거부 처리자로 지정함
customAccessDenied 객체를 reference(참조-바라본다)함-->
<security:access-denied-handler ref="customAccessDenied"/>
<!-- 데이터소스를 지정하고 테이블을 이용해서 기존 로그인 정보를 기록
쿠키의 유효시간을 지정함
token-validity-seconds : 쿠키의 유효시간(초) 604800초는 7일 -->
<security:remember-me data-source-ref="dataSource"
token-validity-seconds="604800"/>
<!-- 로그아웃 처리를 위한 URI를 지정하고, 로그아웃한 후에 세션을 무효화함
customLogoutSuccessHandler(사용자정의 로그아웃 성공 처리자)
JSESSION_ID : 웹브라우저(유일한 세션)의 유일한 세션값을 쿠키에 담고있음.-->
<security:logout logout-url="/logout" invalidate-session="true"
success-handler-ref="CustomLogoutSuccessHandler"
delete-cookies="remember-me,JSESSION_ID" />
</security:http>
<!-- authentication : 인증(로그인)
1) 회원 게시판(board)
가) 목록("/board/list") : 모두가 접근 가능
나) 등록("/board/register") : 로그인한 회원만 접근가능
2) 공지사항 게시판(notice)
가) 목록("/notice/list") : 모두가 접근 가능
나) 등록 ("/notice/register"): 로그인한 관리자만 접근가능
1 회원(USERS)테이블 : USERNAME,PASSWORD, ENABLED
N 권한(AUTH)테이블 : USERNAME, AUTHRIZE
-->
<security:authentication-manager>
<!-- 지정된 아이디와 패스워드로 로그인이 가능하도록 설정
authentication-provider : 인증(로그인) 제공자
-->
<security:authentication-provider user-service-ref="customUserDetailsService">
<!-- DB를 사용하겠다 라는 의미. 데이터 소스를 지정.//dataSource => root-context에 등록한 bean(객체) -->
<!-- <security:jdbc-user-service data-source-ref="dataSource"/> -->
<!-- 사용자가 정의한 비밀번호 암호화 처리기를 지정(암호화를 안쓰겠다는 의미)-->
<security:password-encoder ref="customPassswordEncoder" />
<!-- BCryptPasswordEncoder비밀번호 암호화 처리기를 사용하겠다는 뜻 -->
<!-- <security:password-encoder ref="bcryptPasswordEncoder" /> -->
</security:authentication-provider>
</security:authentication-manager>
</beans>
중
<!-- 사용자정의 사용자 상세 기능 **** 중요-->
<bean id="customUserDetailsService" class="kr.or.ddit.security.CustomUserDetailsService"></bean>
CustomUserDetailsService 클래스
package kr.or.ddit.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import kr.or.ddit.mapper.EmpMapper;
import kr.or.ddit.vo.MemVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class CustomUserDetailsService implements UserDetailsService {
//DI(의존성주입)
@Autowired
EmpMapper empMapper;
//요청파라미터 <input type="text" name="username" ... >
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//파라미터 준비(public MemVO memLogin(MemVO memVO))
MemVO memVO = new MemVO();
//WHERE A.USER_ID = #{userId}
memVO.setUserId(username);
memVO = empMapper.memLogin(memVO);
log.warn("EmpMapper에 의해 쿼리를 실행할 것임 :"+memVO);
//3항 연산자. memVO가 null이면 null을 리턴하고, null이 아니면 USER를 리턴
return memVO==null?null:new CustomUser(memVO);
//return 되는값은 스프링 시큐리티에 보냄
}
}
CustomUser 클래스
package kr.or.ddit.security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import kr.or.ddit.vo.MemAuthVO;
import kr.or.ddit.vo.MemVO;
//User : 스프링 시큐리티가 제공하는 있는 사용자 정보 클래스
public class CustomUser extends User {
//이 memVO 객체는 JSP에서 사용할 수 있음.
private MemVO memVO;
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
//생성자
//memVO : select한 사용자 및 권한 정보가 들어있음
//memVO 타입의 객체 memVO를 스프링 시큐리티에서 제공해주고 있는 UserDetails타입으로 변환
//스프링 시큐리티야 회원정보를 보내줄테니.. 이제부터 니가 좀 관리해줘!
public CustomUser(MemVO memVO) {
//1)username 2)password 3)authorities
//memVO.getMemAuthVOList()
// 2 ROLE_ADMIN
// 2 ROLE_MEMBER
//memVO.getMemAuthVOList().stream()
// 2 ROLE_ADMIN 2.ROLE_MEMBER
//방법1)
// super(memVO.getUserId(),memVO.getUserPw(),
// memVO.getMemAuthVOList().stream().map(auth->new SimpleGrantedAuthority(auth.getAuth()))
// .collect(Collectors.toList()));
// this.memVO = memVO;
//방법2) 아래의 public static List<SimpleGrantedAuthority> getCollect(MemVO memVO) 필요
super(memVO.getUserId(),memVO.getUserPw(),
getCollect(memVO));
this.memVO = memVO;
}
public static List<SimpleGrantedAuthority> getCollect(MemVO memVO){
List<SimpleGrantedAuthority> authorities
= new ArrayList<SimpleGrantedAuthority>();
/*
2 ROLE_ADMIN
2 ROLE_MEMBER
*/
List<MemAuthVO> memAuthVOList = memVO.getMemAuthVOList();
for(MemAuthVO memAuthVO : memAuthVOList) {
//memAuthVO.getAuth() : ROLE_ADMIN
SimpleGrantedAuthority authrity = new SimpleGrantedAuthority(memAuthVO.getAuth());
authorities.add(authrity);
}
return authorities;
}
public MemVO getMemVO() {
return memVO;
}
public void setMemVO(MemVO memVO) {
this.memVO = memVO;
}
}
'JAVA' 카테고리의 다른 글
JAVA 파일업로드 폼 입력시 시큐리티 csrf 추가 (0) | 2023.02.15 |
---|---|
JAVA Spring 시큐리티 애노테이션 (0) | 2023.02.15 |
JAVA SPRING 시큐리티 ajax 데이터 전송 전 헤더에 csrf값 설정하기 (0) | 2023.02.14 |
JAVA Spring security 시큐리티 설정 (0) | 2023.02.13 |
에러페이지 예외처리하기 (0) | 2023.02.10 |
Comments