일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- bean
- Anolog
- Stream
- WIL
- programmers
- jQuery
- oauth
- html
- google oauth
- session
- 항해99
- Hibernate
- jenkins
- spring
- SseEmitter
- 생명주기 콜백
- server send event
- Java
- web
- hanghae99
- python
- DI
- JPA
- flask
- cookie
- Project
- Spring Security
- javascript
- JWT
- real time web
- Today
- Total
끄적끄적 코딩일지
[Spring] Spring Security + OAuth2 (2) - 코드 구현하기 본문
이 글은 저번글에서 Google Console에 OAuth 를 사용하기 위한 사전 준비를 하던 글에서 이어진다.
2022.06.08 - [Spring] - [Spring] Spring Security + OAuth2 (1) - 프로젝트 설정하기
위 글에서 최종적으로 Client Id와 Client 보안 비밀번호를 발급받았을 것이다.
그 정보를 application.properties, application.yml등에 넣으면된다. 이 글에서는 application.properties를 기준으로 설명을 하겠다.
Step 1. 설정하기
spring.security.oauth2.client.registration.google.client-id=클라이언트 ID
spring.security.oauth2.client.registration.google.client-secret=클라이언트 보안 비밀번호
spring.security.oauth2.client.registration.google.scope=profile,email # 가저올 정보
naver, kakao등을 사용할때는 provider 설정을 해주어야 하나 google은 oauth2-client라이브러리에서 기본 설정값이 있어 클라이언트 id, 비밀번호만 설정해도 가능하다.
Step 2. Service 만들기
@RequiredArgsConstructor
@Service
public class OAuthLoginService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
private final MemberRepo repo;
private final HttpSession httpSession;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
// OAuth2UserService에서 request으로 user 정보를 얻어온다.
OAuth2UserService delegate = new DefaultOAuth2UserService();
OAuth2User user = delegate.loadUser(userRequest); // 사용자 요청을 OAuth server으로 보내고 redirection한 값을 받아온다.
// 로그인 진행중인 서비스 구분( google인지 Kakao인지 Naver인지 구분하는 코드 )
String registrationId = userRequest.getClientRegistration().getRegistrationId();
// OAuth2 로그인 진행시 키가 되는 필드값
// 네이버, 카카오등은 지원하지 않는다.
// OAuth2User의 정보를 생성할때 Key값으로 쓰인다.
String userNameAttributeName = userRequest.getClientRegistration()
.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
// 사용자 정보 값
// Google 기준으로 범위에서 설정한 값이 제공된다.
// System.out.println을 통해 사이트별 들어오는 정보를 확인할 수 있다.
Map<String,Object> attrs = user.getAttributes();
for(String key : attrs.keySet()){
System.out.println(key+":"+attrs.get(key));
}
// Email으로 사용자 정보를 검색하여 없으면 만들고 있으면 수정후 업데이트한다.
Member member = saveOrUpdate(attributes);
// 인증 객체를 만들어서 return 한다.
// Collections.emptyList()는 권한 목록이다.
return new DefaultOAuth2User(
Collections.emptyList(),
attrs,
userNameAttributeName
);
}
// 사용자 이름과 프로필 사진 url 정보가 수정되면 바로 업데이트를 하기위한 logic
private Member saveOrUpdate(Map<String,Object> attrs){
Member m = repo.findByEmail(attrs.get("email").toString());
if(m == null){
m = new Member();
m.setEmail(attrs.get("email").toString());
}
m.setName(attrs.get("name").toString());
m.setPicture(attrs.get("picture").toString());
return repo.save(m);
}
}
Member이나 MemberRepo등은 기본적인 사용자 정보라서 따로 언급은 하지 않겠다.
하지만 위에서 user.getAttributes()에서 들어오는 값은
OAuth를 제공하는 서비스마다 다르므로 따로 구분하는 로직을 만들어야 한다.
Step 3. Spring Security 설정
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final OAuthLoginService loginService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.headers().frameOptions().disable()
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/h2-console/**").permitAll()
.anyRequest().authenticated()
.and()
.logout() // 로그아웃 로직에서 쿠키 정보 삭제하도록 구현
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.clearAuthentication(true)
.deleteCookies("JSESSIONID").permitAll()
.and()
.oauth2Login() // oauth2 로그인 설정
.userInfoEndpoint()
.userService(loginService); // 헤당 서비스로 로그인이 진행되도록 설정
return http.build();
}
}
최근 Spring Security에서 Bean 등록만 가지고 설정이 가능하도록 수정되면서 WebSecurityConfiguraterAdapter가 deprecate 되었다.
만약 Adapter을 사용한다면 HttpSecurity를 설정하는 부분에서 구현하면 된다.
Step 4. 사용하기
thymeleaf에서 사용
<!DOCTYPE html>
<html lang="en" xmlns:th=“https://www.thymeleaf.org” xmlns:sec="https://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="//unpkg.com/bootstrap@4/dist/css/bootstrap.min.css">
<script src='//unpkg.com/jquery@3/dist/jquery.min.js'></script>
<script src='//unpkg.com/bootstrap@4/dist/js/bootstrap.min.js'></script>
</head>
<body>
<div class="container">
<div class="row" sec:authorize="!isAuthenticated()" >
<a role="button" href="/oauth2/authorization/google" class="btn btn-outline-primary">Google Login</a>
</div>
<div class="row" sec:authorize="isAuthenticated()">
<a role="button" href="/logout" class="btn btn-outline-danger">logout</a>
</div>
<div class="row" sec:authorize="isAuthenticated()">
<b>Authenticated DTO:</b>
<p th:text="${#authentication}"></p>
</div>
<div class="row" sec:authorize="isAuthenticated()">
<b>Authenticated username:</b>
<p sec:authentication="name"></p>
</div>
</div>
</body>
</html>
위에서 참고해야할것은 button에서 href를 /oauth2/authorization/google으로 설정하는것이다.
해당 url으로 요청이 오면 Oauth2-Client의 대한 기본설정으로 google oauth server으로 요청을 보내게 된다.
밑의 하단정보는 인증을 테스트하기위한 정보이다.
사용을 위해서는 thymeleaf와 thymeleaf-extras-springsecurity5를 사용해야 한다.
dependencies{
....
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
....
}
결과 확인
위처럼 로그인한 결과를 볼 수 있다.
contoller에서 사용
@Contoller
public class TestContoller{
@GetMapping("/principal")
public String getPrincipal(@AuthenticationPrincipal OAuth2User user){
return user.toString();
}
}
'Spring' 카테고리의 다른 글
[Spring] SSeEitter 사용하기 (0) | 2022.06.09 |
---|---|
[Spring] Entity에서 Collection 사용하기 (0) | 2022.06.09 |
[Spring] Spring Security + OAuth2 (1) - 프로젝트 설정하기 (0) | 2022.06.08 |
[Spring] Spring Security + JWT (0) | 2022.06.08 |
[Spring 기초] Scope 사용하기 (0) | 2022.06.07 |