230807 day85 개념 정리

Jin·2023년 9월 2일
0

codenotion

목록 보기
76/90
post-thumbnail

스프링 시큐리티 

1. pom.xml 에 라이브러리 추가 (동일한 버전)
서블릿의 여러 종류의 필터와 인터셉터를 이용해서 처리됨 

spring-security-web
spring-security-core
spring-security-taglibs
spring-security-config


2. 설정 파일 생성 
security-context.xml (WEB-INF/spring 폴더 안에 생성)
네임스페이스 - security 항목 체크

web.xml 필터 추가 

<!-- 스프링 시큐리티가 스프링 mvc에 사용되기 위한 설정 
(필터를 이용해서 스프링 동작에 관여하도록 함) -->
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>	
	</filter>

	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>	
	</filter-mapping>


	<context-param>
		<param-value>
			/WEB-INF/spring/root-context.xml
			/WEB-INF/spring/security-context.xml
		</param-value>
	</context-param>


3. security-context.xml 설정

3-1) 시작점 <security:http>
(메소드 종류) 
perminAll : 모두에게 허용 
hasRole('권한') : 권한이 있는지 체크

3-2) 인증 <security:authentication-manager>

3-3). 접근제한 설정 <security:intercept-url pattrtn="sample/all" access="permitAll">

<security:http>
	<security:intercept-url pattrtn="페이지 경로" access="">
	<security:intercept-url pattrtn="sample/all" access="permitAll">
	<security:intercept-url pattrtn="sample/mamber" access="hasRole('ROLE_MEMBER')">
	<security:intercept-url pattrtn="sample/admin" access="hasRole('ROLE_ADMIN')">
</security:http>

3-4) 로그인 페이지 설정 <security:form-login/>

3-5) 인증(Authentication)과 권한(Authorization) 부여 

Authentication-manager : 인증 매니저 (책임자)

ProviderManager : 인증 제공자 (인증 처리 담당)
-> Authentication-Provider 타입의 객체를 이용해서 처리함 

UserDetailsService : 실제 사용자의 정보와 사용자가 가진 권한의 
정보를 처리해서 반환


<security:authentication-manager>
	<security:authentication-provider>
		<security:user-service>
			<security:user name="member" password="member" authorities="ROLE_MEMBER" />
			<security:user name="admin" password="admin" authorities="ROLE_MEMBER, ROLE_ADMIN" />
		</security:user-service>
	</security:authentication-provider>
</security:authentication-manager>


4. 접근거부 페이지 설정

4-1) error-page 지정하기 

- security-context.xml에 설정
<security:access-denied-handler error-page="/accessError" />

- CommonController에서 /accessError 처리하도록 작성 
@GetMapping("/accessError") ---> accessError.jsp로 이동
public void accessDenied(Authentication auth, Model model) {
	model.addAttribute("msg", "접근 거부");
}

4-2) AccessDeniedHandler 인터페이스 구현하기 
CustomAccessDeniedHandler 클래스 생성 
(AccessDeniedHandler 인터페이스 구현 클래스)

security-context.xml 빈으로 등록 

<security:access-denied-handler>태그의 
error-page 속성 대신에 ref 속성으로 변경

ref 속성 값으로 bean id를 지정 


5. 커스텀 로그인 페이지 설정 

5-1) 로그인 페이지 지정 
<security:form-login login-page="/customLogin" />

5-2) CommonControllrt에 로그인 요청 처리 추가
@GetMapping("/customLogin") ---> customLogin.jsp로 이동
public void loginInput(String error, String logout, Model model) {
	if(error != null) {
		model.addAttribute("error", "로그인 오류 발생");
	}
	if(logout != null) {
		model.addAttribute("logout", "로그아웃");
	}	
}

5-3) customLogin.jsp 생성 
<form method="post" action="/login">
	<input type="text" name="username" />
	<input type="password" name="password" />
	<input type="submit" />
	<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>

5-4) 로그인 성공 처리 후 특정한 동작을 하도록 제어 
AuthenticationSuccessHandler 인터페이스 생성 

- customLoginSuccessHandler 클래스 생성 
(AuthenticationSuccessHandler 인터페이스 구현 클래스)

- security-content.xml에 빈으로 등록 

- authentication-success-handler-ref="customLoginSuccess" 속성 지정


5-5) 로그아웃 처리 
- security-content.xml logout 설정 
<security:logout logout-url="/customLogout" invalidate-session="true">

- CommonController /customLogout 처리 작성 
@GetMapping("/customLogout") ---> customLogout.jsp로 이동
public void logoutGet() {
	
}

- customLogout.jsp 생성 
<form action="/customLogout" method="post">
	<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
	<button>로그아웃</button>
</form>


6. JDBC를 이용한 인증/권한 처리 
Authentication Manager : 인증과 권한 처리 

6-1) 인증이나 정보를 제공하는 존재 (Provider)

6-2) UserDetailsService 인터페이스 구현 존재 활용 

jdbc를 이용하기 위한 설정
<security:user-service>
	<security:user name="member" password="member" authorities="ROLE_MEMBER" />
	<security:user name="admin" password="admin" authorities="ROLE_MEMBER, ROLE_ADMIN" />
</security:user-service>

<security:authentication-manager>
	<security:authentication-provider>
		<security:jdbc-user-service data-source-ref="dataSource" />
	</security:authentication-provider>
</security:authentication-manager>

- default 테이블 생성 방식 
create table users (
	username varchar2(50) not null primary key, 
	password varchar2(50) not null, 
	enabled char(1) default '1'
);

create table authorities (
	username varchar2(50) not null, 
	authority varchar2(50) not null,
	constraint fk_authorities_users foreign key(username) references users(username)
);


- 인증/권한을 위한 테이블 설계 (수업에서 사용한 테이블 생성 방식)
create table tbl_member(
	userid varchar2(50) not null primary key,
	userpw varchar2(100) not null,
	username varchar2(100) not null,
	regidate date default sysdate,
	updatedate date default sysdate
)

create table tbl_member_auth(
	userid varchar2(50) not null,
	auth varchar2(50) not null,
	constraint fk_member_auth foreign key(userid) 
	references tbl_member(userid)
)


BCryptPasswordEncoder 클래스를 이용한 패스워드 보호 

BCryptPasswordEncoder 클래스는 이미 시큐리티 API에 포함되어 있으므로
구현하지 않음 -> bean으로 등록만 해줌!!!

<bean id="bcriptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">

<security:authentication-manager>
	<security:authentication-provider>
		<security:jdbc-user-service data-source-ref="dataSource" 
		users-by-username-query="select userid, userpw, enabled from tbl_member where userid = ?"
		authorities-by-username-query="select userid, auth from tbl_member_auth where userid = ?"		
		/> 
		// users, authorities 추가하는 이유 : default 형식이 아니라 
		// 다른 이름, 방식으로 테이블 설계해서 이 쿼리들을 추가해줌

		<security:password-encoder ref="bcriptPasswordEncoder">
	</security:authentication-provider>
</security:authentication-manager>


7. UserDetailsService 인터페이스 구현 방식 

7-1) 회원 클래스, 회원 권한 클래스 생성 
org.green.domain 패키지 생성 
MemberVO 클래스
AuthVO 클래스

7-2) MemberMapper 인터페이스 생성, MemberMapper.xml 생성 

<resultMap type="org.green.domain.MemberVO" id="memberMap">

</resuleMap>


<resultMap type="org.green.domain.AuthVO" id="authMap">

</resuleMap>


resultMap="memberMap"

<select id="read" resultMap="memberMap">
	select mem.userid, userpw, username, enabled, regidate, updatedate, auth
	from tbl_member mem left outer join tbl_member_auth auth 
	on mem.userid = auth.userid
	where mem.userid = #{userid}
</select>


7-3) CustomerUserDetailsService 클래스 생성
(UserDetailsService 인터페이스 구현)

UserDetailsService 인터페이스의 추상메소드 - loadUserByUsername()

UserDetails 타입 -> 인터페이스

UserDetails 상속받은 User클래스 (자동으로 생성되있음)
(org.springframework.security.core.userdetails.User클래스 
-> UserDetails를 구현하고있음)

User 상속받은 CustomUser클래스 생성 

org.green.security.domain패키지  CustomUser클래스

security-context.xml 

- 클래스를 빈으로 등록 
<bean id="customUserDetailsService" class="org.green.security.CustomUserDetailsService"></bean>

- 인증 제공자 수정 (authentication-provider)
user-service-ref 속성으로 지정
<security:authentication-provider user-service-ref="customUserDetailsService">


8. 스프링 시큐리티 jsp에서 사용하기
사용자 정보 나타내기

8-1) 시큐리티 관련 태그 라이브러리 사용 선언 
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>

8-2) 인증된 데이터 정보 <sec:authentication property="principal" /> 
<sec:authentication property="principal.member.userName">
-> UserDetailsService에서 반환된 객체

8-3) 인가 정보 <sec:authorize /> 
-> 로그인된 상태라면 로그아웃을 나타내고, 로그인되지 않은 
상태라면 로그인을 나타내기 

isAnonymous() 익명의 사용자일 경우 true
(로그인을 하지않은 경우도 포함)

isAuthenticated() 인증된 사용자라면 true
(로그인된 경우도 포함)

<sec:authorize access="isAnonymous()">
	<a href="/customLogin">로그인</a>
</sec:authorize>

<sec:authorize access="isAuthenticated()">
	<a href="/customLogin">로그아웃</a>
</sec:authorize>

profile
신입 개발자의 배웠던 것을 복습하기 위한 블로그입니다.

0개의 댓글