스프링 시큐리티 시리즈
- Spring Boot: 시큐리티(Security) – 1
- Spring Boot: 시큐리티(Security) – 2 – 커스텀 로그인 페이지 만들기
- Spring Boot: 시큐리티(Security) – 3 – 로그인 및 권한 정보를 DB에서 가져오기
- Spring Boot: 시큐리티(Security) – 4 – 로그인 폼을 거치지 않고 컨트롤러에서 로그인
- Spring Boot: 시큐리티(Security) – 5 – 권한별 접근 가능한 페이지를 데이터베이스에 설정하기 (동적 설정)
- Spring Boot Security OAuth2: 커스텀 로그인 페이지 구현
깃허브에서 전체 코드 보기 – https://github.com/ayaysir/spring-boot-security-example-1
스프링 부트 시큐리티에서 자주 변경되는 정보를 분리하는 방법에 대해 알아보겠습니다. (참고 블로그)

Security Config 클래스의 코드에서 위의 빨간색 네모 코드를 데이터베이스에서 가져오는 것으로 바꾸는 작업을 하겠습니다. 이유는 위 네모박스는 자주 변경될 수 있는 부분인데 하드코딩 방식으로 정보가 입력되어 있기 때문입니다.
참고로 컨트롤러(일부)는 다음과 같습니다.
@ResponseBody
@RequestMapping("/adminOnly")
public String adminOnly(Authentication auth) {
return "Secret Page!!"
+ "<br>my roles: "+ auth.getAuthorities().toString();
}
@ResponseBody
@RequestMapping("/userOnly")
public String userOnly(Authentication auth) {
return "USER ONLY"
+ "<br>my roles: "+ auth.getAuthorities().toString();
}
@ResponseBody
@RequestMapping("/userOnly/{sub}")
public String userOnlySub(Authentication auth, @PathVariable("sub") String sub) {
return "USER ONLY SUB PAGE (" + sub + ")"
+ "<br>my roles: "+ auth.getAuthorities().toString();
}
@ResponseBody
@RequestMapping("/everybodyOK")
public String everybodyOK() {
return "EVERYBODY OK";
}
1. 데이터베이스에서 테이블 생성 및 URL, 권한정보를 입력합니다.


프로젝트에 연결되어 있는 DB를 이용해 정보를 입력하면 됩니다. 여기서는 mariadb를 사용하였습니다.
2. 위의 데이터베이스를 가져오는 DAO 등을 작성합니다.
package com.springboot.security.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class SecurityDAO {
@Autowired JdbcTemplate jt;
public List<Map<String, Object>> getAuthReq() {
return jt.query("select * from security_authreq", (rs, rowNum) -> {
Map<String, Object> aRow = new HashMap<>();
aRow.put("id", rs.getInt(1));
aRow.put("url", rs.getString(2));
aRow.put("hasAuthority", rs.getString(3));
aRow.put("date", rs.getString(4));
return aRow;
});
}
}
3. Security Config 클래스 파일에서 하드코딩에 해당하는 부분을 별도 메소드로 교체하고, DB에서 읽어오도록 변경합니다.
(.......)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired private SecurityDAO sd;
@Override
protected void configure(HttpSecurity http) throws Exception {
setAntMatchers(http, "ROLE_");
http.csrf().disable()
// setAntMatchers 메소드로 대체되었음
.formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.addLogoutHandler(new TaskImplementingLogoutHandler()).permitAll().logoutSuccessUrl("/");
}
(.......)
protected void setAntMatchers(HttpSecurity http, String rolePrefix) throws Exception {
List<Map<String, Object>> list = sd.getAuthReq();
System.out.println(list);
for(Map<String, Object> m : list) {
// 쉼표(,)로 구분된 권한 정보를 분리 후 배열로 저장
String[] roles = m.get("hasAuthority").toString().split(",");
// 권한 앞에 접두사(rolePrefix) 붙임
for(int i = 0; i < roles.length; i++) {
roles[i] = rolePrefix + roles[i].toUpperCase();
}
// DB에서 url을 읽어올 때 앞에 '/'이 없다면
// 앞에 '/'를 넣어준다.
String url = m.get("url").toString();
if(url.charAt(0) != '/') {
url = "/" + url;
}
// url, 권한 정보를 넣는다.
http.authorizeRequests()
.antMatchers(url)
.hasAnyAuthority(roles);
}
http.authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated();
}
}
4. 테스트해서 이전 방식과 동일한 결과가 나오는지 확인합니다.
운영자(ROLE_ADMIN)로 접속한 경우


손님(ROLE_GUEST)로 접속한 경우


로그인하지 않고 접속하는 경우

모든 페이지 접속 시도 시 로그인 화면으로 리다이렉트됨

스프링 시큐리티 시리즈
- Spring Boot: 시큐리티(Security) – 1
- Spring Boot: 시큐리티(Security) – 2 – 커스텀 로그인 페이지 만들기
- Spring Boot: 시큐리티(Security) – 3 – 로그인 및 권한 정보를 DB에서 가져오기
- Spring Boot: 시큐리티(Security) – 4 – 로그인 폼을 거치지 않고 컨트롤러에서 로그인
- Spring Boot: 시큐리티(Security) – 5 – 권한별 접근 가능한 페이지를 데이터베이스에 설정하기 (동적 설정)
- Spring Boot Security OAuth2: 커스텀 로그인 페이지 구현





2개의 댓글
yoon · 2021년 3월 23일 5:33 오후
글과 같이 구현한다면 DB 권한이 변경될시 재기동 없이는 권한이 바뀌지 않는 것이 맞겠지요?
재기동 없이 할수 있는 방법이 있을까요?
yoonbumtae (BGSMM) · 2021년 3월 23일 5:46 오후
안녕하세요.
아마 그럴 것 같습니다.
https://soon-devblog.tistory.com/7
제가 참고한 블로그의 [3] URL로 요청이 올 때마다 권한 체크 이 부분에 DB가 변경될때마다 새로고침하는 부분이 설명되어 있는 것 같습니다.
감사합니다.