# 권한 제한
권한이 있는 사용자에게만 해당 기능을 사용할 수 있도록 해봅시다.
---
## 버튼 가리기
일반 사용자에게는 도서의 등록/수정/삭제를 보여지지 않도록 해봅시다.
![Imgur](http://i.imgur.com/9nVV84V.png)
위 화면의 소스코드는 아래와 같습니다.
**views/books/index.jsp**
```jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page pageEncoding="utf-8" session="false"%>
<div class="jumbotron">
<h1>Books INDEX</h1>
<p>views/books/index.jsp</p>
<a href="<c:url value="/books/new" />" class="btn btn-lg btn-primary">도서등록</a>
</div>
<div class="container">
<div class="row">
<c:forEach var="book" items="${books}" varStatus="status">
<div class="col-md-4">
<div class="card">
<img src="<c:url value="${ book.image }" />" class="card-img-top" />
<div class="card-body">
<h3 class="card-title">${ book.title }</h3>
<p class="card-text">Some quick example text to build on the
card title and make up the bulk of the card's content.</p>
<a href="#" class="btn btn-primary">상세보기</a> <a
href="<c:url value='/books/edit/${ book.id }' />"
class="btn btn-info">수정</a> <a
href="<c:url value='/books/delete/${ book.id }' />"
class="btn btn-danger">삭제</a>
</div>
</div>
</div>
</c:forEach>
</div>
</div>
```
위 코드에서 등록/수정/삭제 기능을 하는 버튼들을 가리도록 하겠습니다. 먼저 권한에 따라 뷰 페이지를 보여주고 가릴 수 있도록 태그 라이브러리를 추가해야합니다. 해당 페이지에 아래의 태그라리브러리를 추가해주세요.
**views/books/index.jsp**
```jsp
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="s"%>
... (이하 소스코드 생략)
```
이제 spring security에서 제공하는 태그를 쉽게 사용할 수 있게 되었습니다. 도서 등록 버튼을 일반 사용자에게 보여주지 않도록 해보겠습니다. `s:authorize` 태그를 아래와 같이 추가해줍니다.
**views/books/index.jsp**
```jsp
...
<s:authorize access="hasRole('ADMIN')">
<a href="<c:url value="/books/new" />" class="btn btn-lg btn-primary">도서등록</a>
</s:authorize>
```
코드를 적용하여 도서 등록 버튼을 가리도록 하였습니다.
![Imgur](http://i.imgur.com/INuGaMy.png)
추가적으로 수정/삭제 버튼에 대해서도 같은 작업을 수행합니다.
**views/books/index.jsp**
```jsp
...
<s:authorize access="hasRole('ADMIN')">
<a href="<c:url value='/books/edit/${ book.id }' />" class="btn btn-lg btn-default">수정</a>
<a href="<c:url value='/books/delete/${ book.id }' />" class="btn btn-lg btn-danger">삭제</a>
</s:authorize>
...
```
![Imgur](http://i.imgur.com/0HB2ch7.png)
## 버튼 가리기의 한계
위에서 버튼을 보이지 않도록 하였습니다. 하지만 그렇다고 해서 해당 기능을 완전히 사용할 수 없는 것은 아닙니다. 예를 들면 관리 기능의 버튼(등록/수정/삭제 등..)의 링크주소를 알고있는 경우, 직접 타이핑 해서 기능을 사용할 수 있습니다.
## URL 접근 제한하기
위의 문제를 해결하기 위해, 추가적으로 url 권한 인증을 설정해야 합니다. url 접근 인증은 스프링 시큐리티 xml을 통하여 할 수 있습니다.
**security-context.xml**
```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:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- 스프링 시큐리티 설정의 거의 모든 것 -->
<sec:http pattern="/css/**" security="none" />
<sec:http pattern="/img/**" security="none" />
<sec:http pattern="/js/**" security="none" />
<sec:http pattern="/uploads/**" security="none" />
<sec:http auto-config='true' use-expressions="true">
<sec:intercept-url pattern="/" access="permitAll" />
<sec:intercept-url pattern="/login" access="permitAll" />
<sec:intercept-url pattern="/signup" access="permitAll" />
<sec:intercept-url pattern="/**" access="hasRole('USER')" />
<sec:form-login login-page="/login"
login-processing-url="/user/login"
default-target-url="/"
username-parameter="email"
password-parameter="password"
authentication-failure-url="/login?error"
always-use-default-target='true' />
<sec:logout invalidate-session="true"
logout-url="/logout"
logout-success-url="/login?logout" />
<!-- disable csrf protection -->
<sec:csrf disabled="true"/>
</sec:http>
<sec:authentication-manager>
<sec:authentication-provider>
<sec:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT email, password, enabled FROM users WHERE email = ?"
authorities-by-username-query="SELECT email, authority FROM authorities WHERE email = ?" />
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
```
위 코드에 관리자 권한에 대한 url을 아래와 같이 추가해 줍니다.
```xml
...
<sec:http auto-config='true' use-expressions="true">
<!-- 관리자 -->
<sec:intercept-url pattern="/admin/**" access="hasRole('ADMIN')" />
<sec:intercept-url pattern="/books/new/**" access="hasRole('ADMIN')" />
<sec:intercept-url pattern="/books/edit/**" access="hasRole('ADMIN')" />
<sec:intercept-url pattern="/books/delete/**" access="hasRole('ADMIN')" />
<!-- 게스트 -->
<sec:intercept-url pattern="/" access="permitAll" />
<sec:intercept-url pattern="/login" access="permitAll" />
<sec:intercept-url pattern="/signup" access="permitAll" />
<!-- 가입자 -->
<sec:intercept-url pattern="/**" access="hasRole('USER')" />
...
```
xml 설정을 완료하였다면 서버를 재시작해주세요. 이제 일반 유저가 관리자 권한 url을 실행시키면 아래와 같이 실행이 거부 됩니다.
![Imgur](http://i.imgur.com/jwuwvmE.png)