Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 백트래킹
- HttpMessageConverters
- 브루트포스
- 정적 리소스
- AuthenticationPrincipal
- @Profile
- Application Event
- 스프링 부트
- @ConfigurationProperties
- 다익스트라
- Application Runner
- rest api
- cors
- 알고리즘
- HATEOAS
- webjar
- 외부설정
- EnableAutoConfiguration
- 리소스 서버
- JsonSerializer
- 백기선
- 백준
- Application Argument
- Spring Security
- 리소스핸들러
- 스프링부트
- application.properties
- OAuth2
- JPA
- WebApplication Type
Archives
- Today
- Total
아카이브
[스프링 기반 REST API 개발] 시큐리티 현재 사용자 조회하기 본문
SecurityContext
- 자바 ThreadLocal 기반 구현으로 인증 정보를 담고 있다.
- ※ ThreadLocal ? 오직 한 Thread에 의해서 read/write 가능한 variable을 생성할 수 있도록 하는 것(Thread Local Variable)
- 인증 정보를 꺼내는 방법
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// Anonymous인 경우 principal = "anonymousUser" 로 String 이다.
@AuthenticationPrincipal spring.security.User user
- 인증을 안했다 ? null : username과 authorities 참조 가능
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account")
queryEvents를 호출할때 user가 있는 경우 create-event link 추가
@GetMapping
public ResponseEntity queryEvents(Pageable pageable, PagedResourcesAssembler<Event> assembler,
@CurrentUser Account account) {
// @CurrentUser Account account는 @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account") 이다
Page<Event> page = this.eventRepository.findAll(pageable);
PagedModel<EntityModel<Event>> entityModels = assembler.toModel(page, EventResource::new);
entityModels.add(new Link("/docs/index.html#resources-events-list").withRel("profile"));
if (account != null) {
entityModels.add(linkTo(EventController.class).withRel("create-event"));
}
return ResponseEntity.ok(entityModels);
}
spring.security.User를 상속받는 클래스를 구현하면 User 도메인을 받을 수 있다.
UserDetails로 부터 받을 수 있는 security.User 대신에 Account 도메인으로 받기 위해 Adapter를 구현한다.
- @AuthenticationPrincipal을 이용하여 Account 객체 가져오기 위함
- Adapter.getAccount().getId()
AccountAdapter 구현하기
public class AccountAdapter extends User {
private Account account;
public AccountAdapter(Account account) {
super(account.getEmail(), account.getPassword(), authorities(account.getRoles()));
this.account = account;
}
public Account getAccount() {
return account;
}
private static Collection<? extends GrantedAuthority> authorities(Set<AccountRole> roles) {
return roles.stream()
.map(r -> new SimpleGrantedAuthority("ROLE_" + r.name()))
.collect(Collectors.toSet());
}
}
AccountService의 loadByUsername이 AccountAdapter를 리턴하도록 수정하기
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountRepository.findByEmail(username)
.orElseThrow(() -> new UsernameNotFoundException(username));
return new AccountAdapter(account);
}
- AccountAdapter는 User를 상속하고 있고, User는 UserDetails를 구현하고 있다.
@AuthenticationPrincipal 을 사용할 경우, anonymousUser인 경우 Object가 아니라 'anonymousUser' String이 넘어와서 오류가 발생할 수 있다.
그래서 expression에 Object를 반환할 수 있도록, 아래와 같이 설정해야 한다.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account")
public @interface CurrentUser {
}
'Spring > 스프링 기반 REST API 개발' 카테고리의 다른 글
[스프링 기반 REST API 개발] 출력값 제한하기 JsonSerializer<T> (0) | 2021.01.09 |
---|---|
[스프링 기반 REST API 개발] 시큐리티 OAuth2 리소스 서버 설정하기 (0) | 2021.01.09 |
[스프링 기반 REST API 개발] 시큐리티 OAuth2 인증 서버 설정하기 (0) | 2021.01.09 |
[스프링 기반 REST API 개발] 시큐리티 폼 인증 설정하기 (0) | 2021.01.09 |
[스프링 기반 REST API 개발] 시큐리티 기본 설정하기 (0) | 2021.01.09 |