์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |
- ํฌ๋กค๋ง
- OS
- ์ด์์ฒด์
- python
- ์ด์งํ์
- Crawling
- ๋จ์ํ ์คํธ
- ํด์๋ฒ
- ์นด์นด์ค
- ์นํฌ๋กค๋ง
- ์ ๋ ๋์
- ๋งคํธ๋ฉ
- ์ผ์ฑ๊ธฐ์ถ
- ๋ฐฑ์ค
- matlab
- ํ์ด์ฌ
- spring
- ์นด์นด์ค๊ธฐ์ถ
- webcrawling
- ์์์ฒ๋ฆฌ
- API
- ํ๋ก๊ทธ๋๋จธ์ค
- ํด์
- Java
- BFS
- ์๊ณ ๋ฆฌ์ฆ
- ToyProject
- JPA
- selenium
- ๊ทธ๋ฆฌ๋
DevKim
[์คํ๋ง with AWS] ๊ตฌ๊ธ,๋ค์ด๋ฒ ๋ก๊ทธ์ธ ์ฐ๋ ๋ณธ๋ฌธ
๐CH.05 ์คํ๋ง ์ํ๋ฆฌํฐ์ OAuth 2.0์ผ๋ก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ๊ตฌํ๐
* TODO : ๋ฆฌํฉํ ๋ง *
IndexController์์ ์ธ์ ๊ฐ์ ๊ฐ์ ธ์ค๋ ๋ถ๋ถ, ์ฆ (SessionUser) httpSession.getAttribute ~ ๋ถ๋ถ์
๋ค๋ฅธ ์ปจํธ๋กค๋ฌ๋ ๋ฉ์๋์์ ์ธ์ ๊ฐ์ด ํ์ํ ๋๋ง๋ค ๋ฐ๋ณต๋๋ ์ฝ๋๋ก, ๊ฐ์ ์ด ํ์ํ ๋์ ์ฝ๋์ด๋ค.
์ด๋ฅผ ๋ฉ์๋ ์ธ์๋ก ์ธ์ ๊ฐ์ ๋ฐ๋ก ๋ฐ์ ์ ์๋๋ก ๋ณ๊ฒฝํ๋ ๋ถ๋ถ์ ์ง๊ธ ๋จ๊ณ์์ ์ดํดํ๊ธฐ ์ด๋ ค์ด ๋ถ๋ถ์ด ์๊ธฐ ๋๋ฌธ์ ๋์ค์ todo๋ก ๋จ๊ฒจ๋๊ฒ ๋ค.
https://console.cloud.google.com/
Google Cloud Platform
ํ๋์ ๊ณ์ ์ผ๋ก ๋ชจ๋ Google ์๋น์ค๋ฅผ Google Cloud Platform์ ์ฌ์ฉํ๋ ค๋ฉด ๋ก๊ทธ์ธํ์ธ์.
accounts.google.com
OAuth ํด๋ผ์ด์ธํธ ID๋ฅผ ์์ฑํด์ฃผ๊ณ , ๊ทธ์ ๋ฐ๋ฅธ ID์ ClientSecret ์ฝ๋๋ฅผ ๋ฐ์๋์ด์ผํ๋ค.
1. application.properties์ ๊ฐ์ ์์น์ application-oauth-properties ์์ฑ
* ์คํ๋ง ๋ถํธ์์๋ properties์ด๋ฆ์ application-XXX.properties๋ก ๋ง๋ค๋ฉด,
XXX์ด๋ผ๋ profile์ด ์์ฑ๋์ด ์ด๋ฅผ ํตํด ๊ด๋ฆฌํ ์ ์๋ค๊ณ ํ๋ค.
spring.security.oauth2.client.registration.google.client-id=ํด๋ผ์ด์ธํธ ID
spring.security.oauth2.client.registration.google.client-secret=ํด๋ผ์ด์ธํธ ๋ณด์ ๋น๋ฐ
spring.security.oauth2.client.registration.scope=profile,email
scope์ ๊ธฐ๋ณธ๊ฐ์ openid,profile,email์ด๋, openid๋ผ๋ scope์ด ์์ผ๋ฉด ๊ตฌ๊ธ๊ณผ ๊ตฌ๊ธ์ด ์๋ ์๋น์ค(๋ค์ด๋ฒ)๋ก ๋๋ ์ ๊ฐ๊ฐ์ OAuth2Service๋ฅผ ๋ง๋ค์ด์ผํ๋ฏ๋ก, ํ๋๋ก ์ฌ์ฉํ๊ธฐ ์ํด openid scope์ ๋นผ๊ณ ๋ฑ๋กํ๋ค.
2. application-properties์์ application-oauth-properties๋ฅผ ํฌํจํ๋๋ก ๊ตฌ์ฑํ๋ค.
spring.profiles.include=oauth
๐์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ด๋นํ ๋๋ฉ์ธ User ํด๋์ค ์์ฑ
@Getter
@NoArgsConstructor
@Entity
public class User extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String email;
@Column
private String picture;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private Role role;
@Builder
public User(String name, String email, String picture, Role role) {
this.name = name;
this.email = email;
this.picture = picture;
this.role = role;
}
}
๐ ๊ฐ ์ฌ์ฉ์์ ๊ถํ์ ๊ด๋ฆฌํ Enum ํด๋์ค Role ์์ฑ
* ์คํ๋ง ์ํ๋ฆฌํฐ์์๋ ๊ถํ ์ฝ๋์ ํญ์ ROLE_์ด ์์ ์์ด์ผ๋ง ํ๋ค.
@Getter
@RequiredArgsConstructor
public enum Role {
GUEST("ROLE_GUEST","์๋"),
USER("ROLE_USER","์ผ๋ฐ ์ฌ์ฉ์");
private final String key;
private final String title;
}
3. ์คํ๋ง ์ํ๋ฆฌํฐ ์ค์
๐ @EnableWebSecurity
: ์คํ๋ง ์ํ๋ฆฌํฐ ์ค์ ๋ค ํ์ฑํ
๐ authorizeRequests
: url ๋ณ ๊ถํ ๊ด๋ฆฌ ์ค์ ํ๋ ์ต์ ์ ์์์
๐ antMatchers
: ๊ถํ ๊ด๋ฆฌ ๋์์ ์ง์ ํ๋ ์ต์
๐ anyRequest
: ์ค์ ๋ ๊ฐ๋ค ์ด์ธ ๋๋จธ์ง url๋ค
๐ userInfoEndpoint
: OAuth 2 ๋ก๊ทธ์ธ ์ฑ๊ณต ์ดํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ๋์ ์ค์ ๋ค์ ๋ด๋น
๐ userService
: ์์ ๋ก๊ทธ์ธ ์ฑ๊ณต ํ, ํ์ ์กฐ์น๋ฅผ ์งํํ UserService ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ฅผ ๋ฑ๋ก
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CustomOAuth2UserService customOAuth2UserService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.headers().frameOptions().disable()
.and()
.authorizeRequests()
.antMatchers("/","/css/","/images/**","/js/**","h2-console/**").permitAll()
.antMatchers("/api/v1/**").hasRole(Role.USER.name())
.anyRequest().authenticated()
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.oauth2Login()
.userInfoEndpoint()
.userService(CustomOAuth2UserService);
}
}
๐ CustomOAuth2UserService ํด๋์ค ์์ฑ
: ๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ดํ ๊ฐ์ ธ์จ ์ฌ์ฉ์ ์ ๋ณด(์ด๋ฉ์ผ,์ด๋ฆ,์ฌ์ง..)๋ค์ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์ ๋ฐ ์ ๋ณด์์ ,์ธ์ ์ ์ฅ ๋ฑ์ ๊ธฐ๋ฅ์ ์ง์
@RequiredArgsConstructor
@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
private final UserRepository userRepository;
private final HttpSession httpSession;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2UserService delegate = new DefaultOAuth2UserService();
OAuth2User oAuth2User = delegate.loadUser(userRequest);
//ํ์ฌ ์งํ ์ค์ธ ์๋น์ค ๊ตฌ๋ถ
String registrationId = userRequest.getClientRegistration().getRegistrationId();
//OAuth2 ๋ก๊ทธ์ธ ์งํ์ ํค๊ฐ๋๋ ํ๋๊ฐ(=PK)
String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails()
.getUserInfoEndpoint().getUserNameAttributeName();
//OAtuth2User์ ์์ฑ๋ค์ ๋ด์ ํด๋์ค(=dto)
OAuthAttributes attributes = OAuthAttributes.of(registrationId, userNameAttributeName, oAuth2User.getAttributes());
User user = saveOrUpdate(attributes);
httpSession.setAttribute("user", new SessionUser(user));
return new DefaultOAuth2User(
Collections.singleton(new SimpleGrantedAuthority(user.getRoleKey())),
attributes.getAttributes(),
attributes.getNameAttributeKey());
}
private User saveOrUpdate(OAuthAttributes attributes) {
User user = userRepository.findByEmail(attributes.getEmail())
.map(entity -> entity.update(attributes.getName(), attributes.getPicture()))
.orElse(attributes.toEntity());
return userRepository.save(user);
}
}
๐ registrationId
: ํ์ฌ ๋ก๊ทธ์ธ ์งํ ์ค์ธ ์๋น์ค ๊ตฌ๋ถ (๊ตฌ๊ธ,๋ค์ด๋ฒ..)
๐ userNameAttributeName
: OAuth2 ๋ก๊ทธ์ธ ์งํ์ ํค๊ฐ๋๋ ํ๋๊ฐ(PK์ ์ ์ฌ)
๐ OAuthAttributes
: OAuth2User์ ์์ฑ๋ค์ ๋ด์ ํด๋์ค(=dto)
๐ SessionUser
: ์ธ์ ์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ธฐ ์ํ DTO ํด๋์ค
-> User ํด๋์ค๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ์ง ์๋ ์ด์ ๋, User๋ ์ํฐํฐ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ค ๊ฒ๊ณผ ์ฐ๊ด๊ด๊ณ๊ฐ ์ฑ๋ฆฝ๋์ด์์ ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ด๋ค. ( ์ฑ๋ฅ ์ด์,๋ถ์ ํจ๊ณผ ๋ฐ์ ๋ฐฉ์ง)
* ์ฐธ๊ณ ๋ก SessionUser์๋ ์ธ์ฆ๋ ์ฌ์ฉ์ ์ ๋ณด๋ง ํ์ํ๋ฏ๋ก, name/email/picture๋ง ํ๋๋ก ์ ์ธ *
๐๋ก๊ทธ์ธ ํ ์คํธ
<div class="row">
<div class="col-md-6">
<a href="/posts/save" role="button" class="btn btn-primary">๊ธ ๋ฑ๋ก</a>
{{#MyUser}}
Logged in as: <span id="user">{{MyUser}}</span>
<a href="/logout" class="btn btn-info active" role="button">Logout</a>
{{/MyUser}}
{{^MyUser}}
<a href="/oauth2/authorization/google" class="btn btn-success active" role="button">Google Login</a>
{{/MyUser}}
</div>
</div>
<br>
๐ {{^username}}
: username์ด ์๋ค๋ฉด, ์คํ๋ง ์ํ๋ฆฌํฐ์์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ ๋ก๊ทธ์ธ url๋ก ์ด๋
๐ Controller์ ์ธ์ user name๊ฐ ์ถ๊ฐ
private final HttpSession httpSession;
@GetMapping("/")
public String index(Model model)
{
List<Posts> postsList = postsRepository.findAllDesc();
model.addAttribute("posts",postsList);
//SessionUser์ ์ ์ฅํ ๋ก๊ทธ์ธ ์ ๋ณด
SessionUser user = (SessionUser) httpSession.getAttribute("user");
if(user!=null)
{
model.addAttribute("MyUser",user.getName());
}
return "index";
}
*์ด๋ ์ฃผ์ํ ์ *
window ์ฌ์ฉ์๋ userName ์ด๋ผ๋ ๋ณ์๊ฐ ์์คํ ๋ณ์ ์์์ ์ด๋ฏธ ์ฌ์ฉ๋๊ณ ์์ผ๋ฏ๋ก,
userName์ด๋ผ๋ ๊ฐ์ผ๋ก ๋ฐ์ผ๋ฉด ๋ด ์ปดํจํฐ ์ฌ์ฉ์์ ์ด๋ฆ์ด ๋ฐ์์ค๊ฒ ๋๋ค.
userName๋ง๊ณ ๋ค๋ฅธ ๋ณ์(์ฌ๊ธฐ์๋ MyUser) ๋ก ๊ฐ์ ๋๊ฒจ์ฃผ์
๐ ๋์ ํ์ธ
โผ
๊ตฌ๊ธ ๋ก๊ทธ์ธ
โผ
๋ค์ด๋ฒ ๋ก๊ทธ์ธ