[spring] 요청 경로 매핑, form, 시큐리티, 로그인/로그아웃

dev_hnbm·2024년 1월 28일
0

대덕인재개발원

목록 보기
29/30

⚡ 요청 경로 매핑

@RequestMapping

  • 클래스 레벨과 메서드 레벨에서 요청 경로를 지정할 수 있음
  • 클래스 레벨에서 지정한 요청 경로에 메서드 레벨에서 지정한 요청 경로가 덧붙여서 최종 경로가 됨

1. void 타입

/*
	요청 URI: /board/registerTest
	요청 파라미터: 
	요청 방식: get
	리턴 타입: void
*/
@RequestMapping(value = "/registerTest", method = RequestMethod.GET)
public void registerTest() {
	log.info("registerTest");
}

2. String 타입

/*
	요청 URI: /board/100, /board/101 (게시판의 100번째 글, 101번째 글 -> 경로(path) 변수(variable) 매핑)
	요청 파라미터: 
	요청 방식: get
	리턴 타입: String
	
	* path variable mapping: BoardVO의 boardNo 프로퍼티
*/
@RequestMapping(value = "/{boardNo}")
public String read(@PathVariable("boardNo") int boardNo) {
	log.info("read() boardNo: " + boardNo);
	return "board/read"; // forwarding, /WEB-INF/board/read.jsp를 리턴
}

/*
	요청 URI: /board/stud/1, /board/stud/2
	요청 파라미터: 
	요청 방식: get
	리턴 타입: String
	
	* path variable mapping: BoardVO의 seq 프로퍼티
*/
@RequestMapping(value = "/stud/{seq}")
public String readTest(@PathVariable("seq") int seq) {
	log.info("readTest() seq:" + seq);
	return "board/read";
}

3. 파라미터 매핑

메서드 분기 처리시 용이 (수정, 삭제 버튼 등)

/* params mapping
		요청 URI: /board/read?register
		요청 파라미터: register
		요청 방식: get
	*/
	@RequestMapping(value = "/read", method = RequestMethod.GET, params = "register") // /board/read?register
	public String readParams() {
		log.info("readParmas");
		return "board/read";
	}

4. 폼 데이터 받기

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<div class="card card-primary">
	<div class="card-header">
		<h3 class="card-title">Quick Example</h3>
	</div>

	<form action="/board/read?register" method="post">
		<div class="card-body">
			<div class="form-group">
				<label for="exampleInputEmail1">Email address</label> 
				<input type="email" name="memEmail" class="form-control" id="memEmail" placeholder="Enter email">
			</div>
			<div class="form-group">
				<label for="exampleInputPassword1">Password</label> 
				<input type="password" name="memPass" class="form-control" id="memPass" placeholder="Password">
			</div>
			<div class="form-group">
				<label for="exampleInputFile">File input</label>
				<div class="input-group">
					<div class="custom-file">
						<input type="file" name="uploadFile" class="custom-file-input" id="uploadFile">
						<label class="custom-file-label" for="exampleInputFile">Choose file</label>
					</div>
					<div class="input-group-append">
						<span class="input-group-text">Upload</span>
					</div>
				</div>
			</div>
			<div class="form-check">
				<input type="checkbox" class="form-check-input" id="exampleCheck1">
				<label class="form-check-label" for="exampleCheck1">Check me out</label>
			</div>
		</div>

		<div class="card-footer">
			<!-- 
				* params mapping
				요청 URI: /board/read?register
				요청 파라미터: register
				요청 방식: get
			-->
			<a href="/board/read?register" class="btn btn-primary">Submit(register/get)</a>
			<!-- 
				* params mapping
				요청 URI: /board/read?register
				요청 파라미터: register
				요청 방식: post
			-->
			<button type="submit" class="btn btn-primary">Submit(register/post)</button>
			<!-- 
				* params mapping
				요청 URI: /board/read?modify
				요청 파라미터: modify
				요청 방식: get
			-->
			<a href="/board/read?modify" class="btn btn-primary">Submit(modify)</a>
		</div>
	</form>
</div>



📋 form

일반 form

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<form name="studVO" id="studVO" action="/springform/register" method="post">
	<table>
		<tr>
			<th>학생ID</th>
			<td><input type="text" name="studId" id="studId" /></td>
		</tr>
		<tr>
			<th>학생명</th>
			<td><input type="text" name="studNm" id="studNm" /></td>
		</tr>
		<tr>
			<th>학생비밀번호</th>
			<td><input type="text" name="studPw" id="studPw" /></td>
		</tr>
	</table>
	<button type="submit">등록</button>
</form>

스프링 form

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<!-- 
	요청 URI: /springform/register
	요청 파라미터: {studId=a005,studNm=개똥이,studPw=java}
	요청 방식: post
-->
<form:form modelAttribute="studVO" action="/springform/register" method="post">
	<table>
		<tr>
			<th>학생ID</th>
			<!-- 
				- form:input랑 input type="text"는 동일
				- path 속성은 name, id 속성을 합친 것 
			-->
			<td><form:input path="studId" /></td>
		</tr>
		<tr>
			<th>학생명</th>
			<td><form:input path="studNm" /></td>
		</tr>
		<tr>
			<th>학생비밀번호</th>
			<td><form:password path="studPw" /></td>
		</tr>
	</table>
	<!-- form:button 자체가 type="submit" -->
	<form:button name="register">등록</form:button>
</form:form>

스프링 폼 태그 라이브러리

  • 스프링 폼은 HTML 폼을 표시하기 위한 태그 라이브러리이며, HTML 폼과 자바 객체를 쉽게 바인딩 할 수 있음
  • 뷰(jsp)와 Controller가 자바 객체를 공유해서 사용할 수 있음
    • jsp의 modelAttribute 속성으로 지정한 이름과 Controller 변수가 동일시 연동

규칙

  1. 폼 객체의 속성명과 스프링 폼 태그의 modelAttribute 속성값이 일치해야 함

  2. 컨트롤러 메서드의 매개변수로 자바빈즈 객체가 전달되면 Model 클래스를 사용하지 않아도 forwarding하는 JSP에 다시 화면으로 전달함

  3. 폼 객체의 속성명은 직접 지정하지 않을시 (@ModelAttribute("studVO") 폼 객체 클래스명의 맨 첫문자를 소문자로 변환하여 처리

  4. @ModelAttribue 어노테이션으로 폼 객체의 속성명을 직접 지정할 수 있음

  5. 폼 객체의 프로퍼티 값을 지정하여 (setter()) 모델을 통해 전달할 수 있음
    -> model.addAttribute("얘", VO)modelAttribute="얘"랑 일치
    혹은
    -> public String register(얘앞글자소문자 studVO)modelAttribute="얘" 일치 (VO 프로퍼티명과 form name 속성값이 일치)
    후자가 Model을 사용하지 않아도 되니까 쌤이 추천하는 방법

폼 항목의 공통 속성

  1. path 폼 항목에 바인딩되는 폼 객체의 프로퍼티 지정
  2. disabled 폼 항목을 비활성화할지 여부 (기본값: false)
  3. readonly 폼 항목을 읽기 전용으로 할지 여부 (기본값: false)




🛡 스프링 시큐리티

기본 보안 기능

  • 인증(Authentication): 애플리케이션 사용자의 정당성 확인 (로그인)
  • 인가(Authorization): 애플리케이션의 리소스나 처리에 대한 접근 제어 (로그인 후의 권한)

시큐리티 제공 기능

  • 세션 관리
  • 로그인 처리
  • CSRF 토큰 처리
  • 암호화 처리
  • 자동 로그인

시큐리티 표현식

인증 정보와 권한 정보를 다룰 수 있음 로그인한 사용자의 정보를 확인함

1. 인증 정보

  • isAuthenticated 로그인 되었다면 true
  • isAnonymous 로그인 안 되었다면 true
  • principal 로그인한 사용자 정보 (UserDetails 인터페이스를 구현한 클래스의 객체)

2. 권한 정보

  • hasRole(role명) 해당 role이 있으면 true
  • hasAnyrole(role명1, role명2) 여러 role 중 하나라도 해당되는가?




🪬 로그인/로그아웃

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">
	
	<bean id="customAccessDenied" class="kr.or.ddit.security.CustomAccessDeniedHandler"></bean>
	<bean id="customLoginSuccess" class="kr.or.ddit.security.CustomLoginSuccessHandler"></bean>
	
	<security:http>
		<!-- URI 패턴으로 접근 제한 -->
		<security:intercept-url pattern="/brd/list" access="permitAll" />
		<security:intercept-url pattern="/brd/register" access="hasRole('ROLE_MEMBER')" />
		<security:intercept-url pattern="/notice/list" access="permitAll" />
		<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" />
		<security:intercept-url pattern="/stud/list" access="hasRole('ROLE_ADMIN')" />
		<!-- 도서등록: /create -->
		<security:intercept-url pattern="/create" access="hasRole('ROLE_ADMIN')" />
		
		
		<!-- 폼 기반 인증 기능 사용 (인증(authentication)을 위해 ID/PW 입력받아 체크) -->
		<!-- <security:form-login /> -->
		
		<!-- 사용자 정의 로그인 페이지의 URI 지정 -->
		<!-- 로그인 성공 처리자 
			ref: bean을 바라봄
		-->
		<security:form-login login-page="/login" authentication-success-handler-ref="customLoginSuccess" />
		
		<!-- 접근 거부 처리자 (HTTP 상태 403 – 금지됨: 권한 없음) -->
		<!-- <security:access-denied-handler error-page="/accessError" /> -->
		<!-- 접근 거부가 발생한 상황에 단순 메시지 처리 이상의 다양한 처리를 하고자 할때 사용자가 직접 구현할 수 있음 -->
		<security:access-denied-handler ref="customAccessDenied" />
		
		<!-- 로그아웃 처리를 위한 URI를 지정하고, 로그아웃 후 세션 무효화 -->
		<security:logout logout-url="/logout" invalidate-session="true" />
	</security:http>
	
	<!-- 지정된 ID, PW로 로그인 가능하도록 설정 -->
	<!-- 
		스프링 시큐리니티 5부터 기본적으로 PasswordEncoder를 지정해야 하는데,
		그 이유는 사용자 테이블(USERS)에 비밀번호를 암호화하여 저장해야 하므로..
		우리는 우선 비밀번호를 암호화 처리 하지 않았으므로
		암호화 하지 않는 PasswordEncoder를 직접 구현하여 지정하기로 함
		noop: no option password
	-->
	<security:authentication-manager>
		<security:authentication-provider>
			<security:user-service>
				<security:user name="member" password="{noop}java" authorities="ROLE_MEMBER" />
				<security:user name="admin" password="{noop}java" authorities="ROLE_MEMBER, ROLE_ADMIN" />
			</security:user-service>
		</security:authentication-provider>
	</security:authentication-manager>
</beans>

0개의 댓글