λ©μλ κΆν κ΄λ¦¬
μ€νλ§ μνλ¦¬ν° μ€μ ν΄λμ€κ° μλ,
컨νΈλ‘€λ¬ μμ² λ©μλμμ λ©μλ μμ€μμμ κΆνμ κ΄λ¦¬νλ λ°©λ²
μ μ©λ°©λ²
β’
μ€νλ§ μνλ¦¬ν° μ€μ ν΄λμ€(SecurityConfig.java)
β¦
@EnableMethodSecurity (spring boot 3.2~)
β¦
@EnableGlobalMethodSecurity (spring boot ~3.2)
β’
컨νΈλ‘€λ¬ λ©μλμ κΆν μ μ΄
β¦
@Secured
β¦
@PreAuthorize
β¦
@PostAuthorize
μ€νλ§ μνλ¦¬ν° μ€μ ν΄λμ€(SecurityConfig.java)
β’
@EnableMethodSecurity (spring boot 3.2~)
β’
@EnableGlobalMethodSecurity (spring boot ~3.2)
@EnableMethodSecurity
spring boot 3.2 λ²μ λΆν°λ
@EnableGlobalMethodSecurity λ depreacated
@EnableMethodSecurity κΆμ₯
λ©μλ μμ€μμμ 보μ μ€μ κΈ°λ₯μ νμ±ννλ μ΄λ
Έν
μ΄μ
μ£Όμ μμ±
μμ± | μ€λͺ
| μ¬μ© μμ |
securedEnabled | @Secured μ΄λ
Έν
μ΄μ
νμ±ν
- μν (Role) κΈ°λ° μ κ·Ό μ μ΄λ₯Ό κ°λ₯νκ² ν¨ | @Secured("ROLE_ADMIN") |
prePostEnabled | @PreAuthorize λ° @PostAuthorize μ΄λ
Έν
μ΄μ
μ νμ±ν
- ννμ κΈ°λ° μ μ΄λ₯Ό κ°λ₯νκ² ν¨ | @PreAuthorize("hasRole('ADMIN')")
@PostAuthorize("returnObject.username == authentication.name") |
securedEnabled = true
μν (Role; κΆν) κΈ°λ°μΌλ‘ κ°λ¨ν κΆν μ μ΄
@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {
Java
볡μ¬
@Secured("ROLE_USER")
@GetMapping("/path/to")
public String getMethod() {
}
Java
볡μ¬
ROLE_USER, ROLE_ADMIN λ±μ κΆνμ κ°μ§ μ¬μ©μ μμ²λ§ μ²λ¦¬κ° λλλ‘ νν°λ§νκ² λ©λλ€.
prePostEnabled = true
@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
}
Java
볡μ¬
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/path/to")
public String getMethod() {
}
Java
볡μ¬
μ μ©λλ μ£Όμ νν°
β’
MethodSecurityInterceptor
β¦
λ©μλ 보μμ μ€μ λ‘ μννλ ν΅μ¬ νν°μ
λλ€.
β¦
@Securedμ κ°μ μ΄λ
Έν
μ΄μ
μ κΆν μ μ΄λ₯Ό μ²λ¦¬νλ©°, λ©μλ νΈμΆ μ μ μΈμ¦λ μ¬μ©μμ κΆνμ νμΈν©λλ€.
β’
FilterSecurityInterceptor
β¦
Spring Securityμ HTTP μμ² λ³΄μ νν°λ‘, λ©μλ 보μ보λ€λ URL ν¨ν΄ κΈ°λ°μ μ κ·Ό μ μ΄λ₯Ό μ²λ¦¬ν©λλ€.
@EnableGlobalMethodSecurity
spring boot 3.2 λ²μ λΆν°λ
@EnableGlobalMethodSecurity λ depreacated
@EnableMethodSecurity κΆμ₯
λ©μλ μμ€μμμ 보μ μ€μ κΈ°λ₯μ νμ±ννλ μ΄λ
Έν
μ΄μ
컨νΈλ‘€λ¬ λ©μλμ κΆν μ μ΄
β’
@Secured
β’
@PreAuthorize
β’
@PostAuthorized
μ΄λ
Έν
μ΄μ
| μ μ© μμ | μ£Όμ νΉμ§ |
@Secured | λ©μλ νΈμΆ μ | - μν (Role) κΈ°λ°μ κ°λ¨ν 보μ.
- ROLE_ μ λμ¬ νμ
- SpEL λ―Έμ§μ. |
@PreAuthorize | λ©μλ νΈμΆ μ | - SpELμ μ¬μ©ν ννμ κΈ°λ° λ³΄μ.
- λμ κΆν κ²μ¬ λ° λ³΅μ‘ν 쑰건 μ²λ¦¬ κ°λ₯. |
@PostAuthorize | λ©μλ νΈμΆ ν | - λ°νκ°μ κΈ°λ°μΌλ‘ 보μ κ²μ¬.
- SpEL μ§μ.
- λ°νκ° κΈ°λ°μ 쑰건 μ²λ¦¬ κ°λ₯. |
@Secured
λ¨μν μν (Role) κΈ°λ° κΆν κ²μ¬
- μμ² μ λ¨μμ κΆνμ μ΄
@Controller
@RequestMapping("/board")
public class BoardController {
// μ¬μ©μ κΆν(ROLE_USER)λ₯Ό κ°μ§ μ¬μ©μ μμ²λ§ μ²λ¦¬νλ€.
@Secured("ROLE_USER")
@GetMapping("/{id}")
public String getBoard(@PathVariable("id") String id) {
...
}
}
Java
볡μ¬
@PreAuthorize
λ¨μ κΆν κ²μ¬ λ° SpEL(μ€νλ§ ννμ)μ κΈ°λ°μΌλ‘ 볡μ‘ν 쑰건μ κΆν κ²μ¬
- μμ² μ λ¨μμ κΆνμ μ΄
@Controller
@RequestMapping("/board")
public class BoardController {
// μ¬μ©μ κΆν(ROLE_USER)λ₯Ό κ°μ§ μ¬μ©μ μμ²λ§ μ²λ¦¬νλ€.
@PreAuthorize("hasRole('USER')")
// μ¬μ©μ κΆν(ROLE_USER), κ΄λ¦¬μ κΆν(ROLE_ADMIN)λ₯Ό κ°μ§ μ¬μ©μ μμ²λ§ μ²λ¦¬νλ€.
// @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
@GetMapping("/{id}")
public String getBoard(@PathVariable("id") String id) {
...
}
}
Java
볡μ¬
@PostAuthorized
λ¨μ κΆν κ²μ¬ λ° SpEL(μ€νλ§ ννμ)μ κΈ°λ°μΌλ‘ 볡μ‘ν 쑰건μ κΆν κ²μ¬
- λ©μλ μ€ν ν λ°ν κ°μ λν κΆν κ²μ¬
β’
μμ² μμ(κ²μκΈ)μ λν΄μ μμ±μλ§ μ‘°νκ° κ°λ₯ν κ²½μ°
@RestController
@RequestMapping("/board")
public class BoardController {
@Autowried BoardService boardService;
// λ°νλ κ²μκΈ κ°μ²΄μ userNo μ μΈμ¦λ μ¬μ©μμ User.no κ° μΌμΉνλμ§ νμΈ
@PostAuthorize("returnObject.userNo == authentication.principal.user.no")
@GetMapping("/{id}")
public Board getBoard(@PathVariable("id") String id) {
Board board = boardService.select(id);
String userNo = board.getUserNo();
return board;
}
}
Java
볡μ¬
β’
μλ΅ κ²°κ³Ό
β¦
μμ±μ λ³ΈμΈμΈ κ²½μ°, μμ²ν κ²μκΈ μ λ³΄κ° μλ΅
β¦
μμ±μ λ³ΈμΈμ΄ μλ κ²½μ°, 403 Forbidden μλ¬ μλ΅
β’
returnObject
β¦
μμ² μ»¨νΈλ‘€λ¬ λ©μλμμ λ°ννλ κ°μ²΄λ₯Ό μ°Έμ‘°νλ ν€μλ
β¦
μ¬κΈ°μλ, return board; Board νμ
μ κ²μκΈ μ 보 κ°μ²΄λ₯Ό κ°λ¦¬ν¨λ€.
SpEL( Spring Expression Language ) κΆν μ μ΄ ν¨μ
ν¨μ | μ€λͺ
| μ¬μ© μμ |
hasRole('role') | μ¬μ©μ κΆνμ΄ μ§μ λ μν (role)μΈμ§ νμΈ.
ROLE_ μ λμ¬ μλ΅κ°λ₯
ROLE_ μ λμ¬κ° μλμΌλ‘ λΆμ | @PreAuthorize("hasRole('ADMIN')") |
hasAuthority('authority') | μ¬μ©μ κΆνμ΄ μ§μ λ κΆν(authority)μΈμ§ νμΈ.
ROLE_ μ λμ¬ ν¬ν¨ | @PreAuthorize("hasAuthority('ROLE_USER')") |
isAuthenticated() | μ¬μ©μκ° μΈμ¦λ μνμΈμ§ νμΈ. (λ‘κ·ΈμΈ μ¬λΆ) | @PreAuthorize("isAuthenticated()") |
isAnonymous() | μ¬μ©μκ° μ΅λͺ
(λΉμΈμ¦) μνμΈμ§ νμΈ. | @PreAuthorize("isAnonymous()") |
permitAll() | λͺ¨λ μ¬μ©μκ° μ κ·Όν μ μλλ‘ νμ©. | @PreAuthorize("permitAll()") |
denyAll() | λͺ¨λ μ¬μ©μμ μ κ·Όμ κ±°λΆ. | @PreAuthorize("denyAll()") |
hasPermission(target, permission) | νΉμ λμμ λν΄
νΉμ κΆν(permission)μ κ°μ§κ³ μλμ§ νμΈ. | @PreAuthorize("hasPermission(#post, 'EDIT')") |
principal | νμ¬ μΈμ¦λ μ¬μ©μμ principalμ μ°Έμ‘°. | @PreAuthorize("principal.username == 'admin'") |
κΆν μ μ΄ μμ
β’
μμ μ κ²μ¦ λ‘μ§
β’
κ²μκΈ λ±λ‘
β’
κ²μκΈ μ‘°ν
β’
κ²μκΈ μμ
β’
κ²μκΈ μμ
μμ μ κ²μ¦ λ‘μ§
public interface BoardService {
...
// μμ μ νμΈ
public boolean isOwner(String id, Long userNo) throws Exception;
...
}
Java
볡μ¬
@Slf4j
@Service("BoardService") // β λΉ μ΄λ¦μ BoardService λ‘ μ§μ
public class BoardServiceImpl implements BoardService {
...
/**
* @param id : κ²μκΈ id, userNo : νμ no (PK)
* κ²μκΈ idλ‘ μμ±μ userNo λ₯Ό μ‘°ννμ¬,
* μΈμ¦λ μ¬μ©μ no μ μΌμΉνλμ§ νμΈ
*/
@Override
public boolean isOwner(String id, Long userNo) throws Exception {
log.info("isOwner - id : " + id);
log.info("isOwner - userNo : " + userNo);
Board board = select(id);
Long boardUserNo = board.getUserNo();
if( userNo != null && userNo == boardUserNo ) {
return true;
}
return false;
}
}
Java
볡μ¬
κ²μκΈ λ±λ‘
μΈμ¦λ μ¬μ©μ, μ¦ νμλ§ κ²μκΈμ λ±λ‘ν μ μλ€.
@Controller
@RequestMapping("/board")
public class BoardController {
// κ²μκΈ λ±λ‘ νλ©΄
@Secured("ROLE_USER") // μ¬μ©μ κΆν(ROLE_USER)μΈ κ²½μ°
//@PreAuthorize("hasRole('USER')") // μ¬μ©μ κΆν(ROLE_USER)μΈ κ²½μ°
//@PreAuthorize("isAuthenticated()") // μΈμ¦λ μ¬μ©μ μΈ κ²½μ°
//@PreAuthorize("isAuthenticated() and hasRole('ADMIN')") // μΈμ¦ + κ΄λ¦¬μμΈ κ²½μ°
@GetMapping("/insert")
public String insert() {
...
}
// κ²μκΈ λ±λ‘ μ²λ¦¬
@Secured("ROLE_USER") // μ¬μ©μ κΆν(ROLE_USER)μΈ κ²½μ°
//@PreAuthorize("hasRole('USER')") // μ¬μ©μ κΆν(ROLE_USER)μΈ κ²½μ°
//@PreAuthorize("isAuthenticated()") // μΈμ¦λ μ¬μ©μ μΈ κ²½μ°
//@PreAuthorize("isAuthenticated() and hasRole('ADMIN')") // μΈμ¦ + κ΄λ¦¬μμΈ κ²½μ°
@PostMapping("")
public String insertPost(Board board) {
...
}
}
Java
볡μ¬
κ²μκΈ μ‘°ν
λꡬλ κ²μκΈμ μ‘°νν μ μλ€.
@Controller
@RequestMapping("/board")
public class BoardController {
// λ³λλ‘ κΆνμ μ΄ μ ν¨
@GetMapping("/{id}")
public String select(@PathVariable("id") String id) {
...
return "/board/select";
}
}
Java
볡μ¬
κ²μκΈ μμ
μμ±μ λ³ΈμΈ λλ κ΄λ¦¬λ§ κ²μκΈ μμ μ΄ κ°λ₯νλ€.
@Controller
@RequestMapping("/board")
public class BoardController {
@Autowried BoardService boardService;
// μμ νλ©΄
// π©βπΌ μμ±μ λ³ΈμΈ π©βπ§ κ΄λ¦¬μ
@PreAuthorize(" hasRole('ADMIN') or (#p0 != null and @BoardService.isOwner(#p0, authentication.principal.user.no) )")
@GetMapping("/update/{id}")
public String update(@PathVariable("id") String id) {
Board board = boardService.select(id);
...
}
// μμ μ²λ¦¬
// π©βπΌ μμ±μ λ³ΈμΈ π©βπ§ κ΄λ¦¬μ
@PreAuthorize(" hasRole('ADMIN') or (#p0.id != null and @BoardService.isOwner(#p0.id, authentication.principal.user.no) )")
@ResponseBody
@PutMapping("")
public String update(@RequestBody Board board) {
Board board = boardService.update(board);
...
return "SUCCESS";
}
}
Java
볡μ¬
@PreAuthorize μ΄λ
Έν
μ΄μ
μμμ, SpEL ννμμ μ¬μ©νλ©΄,
#p0, #p1β¦ μ κ°μ νμμΌλ‘ νλΌλ―Έν°λ₯Ό μΈλ±μ€λ‘ μ§μ νμ¬, κ°μ Έμ¬ μ μμ΅λλ€.
public String update(@PathVariable("id") String id) {
...
Java
볡μ¬
μ¬κΈ°μ 첫λ²μ§Έ (μΈλ±μ€ 0 ) νλΌλ―Έν°λ₯Ό κ°μ Έμ€λ €λ©΄, SpEL ννμμμλ #p0 μΌλ‘ μ§μ ν΄μ κ°μ Έμ¬ μ μμ΅λλ€,
νλΌλ―Έν° - @PathVariable("id") String id
SpEL - #p0
id #p0
@BoardService.isOwner(#p0.id, authentication.principal.user.no)
Java
볡μ¬
SpEL ννμ μμμ,
"@λΉμ΄λ¦.λ©μλ" ννλ‘ νΉμ λΉμ λ©μλλ₯Ό νΈμΆν μ μμ΅λλ€.
μ¬κΈ°μμλ λ©μλμ νλΌλ―Έν° id(κ²μκΈ id), μΈμ¦λ μ¬μ©μ no λ₯Ό λ©μλλ‘ μ λ¬νμ¬ μμ μμΈμ§ κ²μ¦νκ³ μ¬λΆλ₯Ό true, false λ‘ λ°νλ°μ μμ μλ₯Ό λ©μλ νΈμΆ μ μ κΆν μ μ΄ ν μ μμ΅λλ€.
κ²μκΈ μμ
μμ±μ λ³ΈμΈ λλ κ΄λ¦¬λ§ κ²μκΈ μμ κ° κ°λ₯νλ€.
@Controller
@RequestMapping("/board")
public class BoardController {
@Autowried BoardService boardService;
// μμ μ²λ¦¬
// π©βπΌ μμ±μ λ³ΈμΈ π©βπ§ κ΄λ¦¬μ
@PreAuthorize("( hasRole('ADMIN')) or (#p0 != null and @BoardService.isOwner(#p0, authentication.principal.user.no))")
@ResponseBody
@DeleteMapping("/{id}")
public String update(@PathVariable("id") String id) {
Board board = boardService.delete(id);
...
return "SUCCESS";
}
}
Java
볡μ¬
μΈμ¦λ μ¬μ©μ κΆνμ΄ κ΄λ¦¬(ROLE_ADMIN) μΈμ§ κ²μ¦ν©λλ€.
νλΌλ―Έν°λ‘ κ²μκΈ id μ μΈμ¦λ μ¬μ©μ no λ°μμ κ²μκΈ μμ μλ₯Ό νμΈν©λλ€.