/*
요청 URI: /board/registerTest
요청 파라미터:
요청 방식: get
리턴 타입: void
*/
@RequestMapping(value = "/registerTest", method = RequestMethod.GET)
public void registerTest() {
log.info("registerTest");
}
/*
요청 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";
}
메서드 분기 처리시 용이 (수정, 삭제 버튼 등)
/* 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";
}
<%@ 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>
<%@ 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>
<%@ 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>
modelAttribute
속성으로 지정한 이름과 Controller 변수가 동일시 연동폼 객체의 속성명과 스프링 폼 태그의 modelAttribute
속성값이 일치해야 함
컨트롤러 메서드의 매개변수로 자바빈즈 객체가 전달되면 Model 클래스를 사용하지 않아도 forwarding하는 JSP에 다시 화면으로 전달함
폼 객체의 속성명은 직접 지정하지 않을시 (@ModelAttribute("studVO"
) 폼 객체 클래스명의 맨 첫문자를 소문자로 변환하여 처리
@ModelAttribue
어노테이션으로 폼 객체의 속성명을 직접 지정할 수 있음
폼 객체의 프로퍼티 값을 지정하여 (setter()
) 모델을 통해 전달할 수 있음
-> model.addAttribute("얘", VO)
랑 modelAttribute="얘"
랑 일치
혹은
-> public String register(얘앞글자소문자 studVO)
랑 modelAttribute="얘"
일치 (VO 프로퍼티명과 form name 속성값이 일치)
후자가 Model을 사용하지 않아도 되니까 쌤이 추천하는 방법
path
폼 항목에 바인딩되는 폼 객체의 프로퍼티 지정disabled
폼 항목을 비활성화할지 여부 (기본값: false)readonly
폼 항목을 읽기 전용으로 할지 여부 (기본값: false)인증 정보와 권한 정보를 다룰 수 있음 로그인한 사용자의 정보를 확인함
1. 인증 정보
isAuthenticated
로그인 되었다면 trueisAnonymous
로그인 안 되었다면 trueprincipal
로그인한 사용자 정보 (UserDetails 인터페이스를 구현한 클래스의 객체)2. 권한 정보
hasRole(role명)
해당 role이 있으면 truehasAnyrole(role명1, role명2)
여러 role 중 하나라도 해당되는가?<?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>