해당 버전은 Google만 적용되어 있습니다.
Google과 facebook 두가지의 소셜로그인이 필요한 경우 다음의 링크에서 확인해주세요 : https://yg1110.tistory.com/8
1. Application structure
2. 구글 API키 받아오기
1) console.developers.google.com/ -> 사용자인증정보 -> 사용자인증정보만들기 -> Oauth 클라이언트 ID만들기 -> 웹어플리케이션
순서로 진행하여 사용자 인증정보를 만듭니다.
만든 클라이언트 ID를 클릭하여 들어가게 될경우 다음과 같은 화면이 보이게 되며,
승인된 리디렉션 URL에 구글 로그인 요청에 사용하고싶은 주소를 넣어주시면 됩니다.
3. application.properties 추가
## google
security.oauth2.client.clientId=clientID
security.oauth2.client.clientSecret=secret_ID
security.oauth2.client.preEstablishedRedirectUri=http://localhost:8080/user/login/result
security.oauth2.client.accessTokenUri=https://www.googleapis.com/oauth2/v4/token
security.oauth2.client.userAuthorizationUri=https://accounts.google.com/o/oauth2/v2/auth
security.oauth2.client.tokenName=oauth_token
security.oauth2.client.authenticationScheme=query
security.oauth2.client.clientAuthenticationScheme=form
security.oauth2.client.scope=profile
security.oauth2.resource.user-info-uri=https://www.googleapis.com/oauth2/v3/userinfo
clientID와 secret_ID부분에 방금 만든 key값을 넣어주시면됩니다.
spring.main.allow-bean-definition-overriding=true
해당 부분은 bean이 중복되는 오류때문에 넣어두었습니다.
4. OAuth2SuccessHandler 생성
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
public class OAuth2SuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse res, Authentication auth)
throws IOException, ServletException {
res.sendRedirect("/user/login/result");
}
}
소셜 로그인 성공시 다음경로로 이동시키는 핸들러입니다.
5. SecurityConfig 수정
@Configuration
@EnableWebSecurity
@EnableOAuth2Client
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/user/admin/**").access("hasAuthority('ROLE_ADMIN')")
.antMatchers("/user/myinfo").access("hasAuthority('ROLE_USER')") // 페이지 권한 설정
.antMatchers("/", "/user/signup", "/user/denied", "/user/logout/result").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class) // 소셜로그인 설정
.formLogin().loginPage("/user/loginPage")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/user/login/result")
.permitAll() // 로그인 설정
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/user/logout")) // 로그아웃 설정
.logoutSuccessUrl("/user/logout/result").invalidateHttpSession(true)
.and()
.exceptionHandling().accessDeniedPage("/user/denied") // 403 예외처리 핸들링
.and()
.csrf().disable();
}
...
@EnableWebSecurity, @EnableOauth2Client 어노테이션을 추가합니다.
기존의 security정보에서 addFilterBefore 부분을 추가합니다.
@Bean
@ConfigurationProperties("security.oauth2.client")
OAuth2ProtectedResourceDetails googleclient() {
return new AuthorizationCodeResourceDetails();
}
@Bean
@ConfigurationProperties("security.oauth2.resource")
ResourceServerProperties googleResource() {
return new ResourceServerProperties();
}
properties에 있는 client와 resource정보를 가져와 사용합니다.
@Autowired
OAuth2ClientContext oauth2ClientContext;
private Filter ssoFilter() {
OAuth2ClientAuthenticationProcessingFilter googleFilter = new OAuth2ClientAuthenticationProcessingFilter("/social_Login"); //해당 경
OAuth2RestTemplate googleTemplate = new OAuth2RestTemplate(googleclient(), oauth2ClientContext);
googleFilter.setRestTemplate(googleTemplate);
googleFilter.setTokenServices(new UserInfoTokenServices(googleResource().getUserInfoUri(), googleclient().getClientId()));
googleFilter.setAuthenticationSuccessHandler(new OAuth2SuccessHandler());
return googleFilter;
}
만약 /social_Login 경로로 요청이 올경우 ssoFilter를 통해 소셜로그인을 진행하게됩니다.
해당 경로는 위에서 지정해둔 리디렉션 주소입니다.
만약 성공적으로 로그인 하였을경우 OAuth2SuccessHandler()에서 지정해둔 경로로 이동시키게됩니다.
전체 소스
import javax.servlet.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.security_blog.yg1110.handler.OAuth2SuccessHandler;
import com.security_blog.yg1110.servicer.UserService;
@Configuration
@EnableWebSecurity
@EnableOAuth2Client
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Autowired
OAuth2ClientContext oauth2ClientContext;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/user/admin/**").access("hasAuthority('ROLE_ADMIN')")
.antMatchers("/user/myinfo").access("hasAuthority('ROLE_USER')") // 페이지 권한 설정
.antMatchers("/", "/user/signup", "/user/denied", "/user/logout/result").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class) // 소셜로그인 설정
.formLogin().loginPage("/user/loginPage")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/user/login/result")
.permitAll() // 로그인 설정
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/user/logout")) // 로그아웃 설정
.logoutSuccessUrl("/user/logout/result").invalidateHttpSession(true)
.and()
.exceptionHandling().accessDeniedPage("/user/denied") // 403 예외처리 핸들링
.and()
.csrf().disable();
}
@Bean
@ConfigurationProperties("security.oauth2.client")
OAuth2ProtectedResourceDetails googleclient() {
return new AuthorizationCodeResourceDetails();
}
@Bean
@ConfigurationProperties("security.oauth2.resource")
ResourceServerProperties googleResource() {
return new ResourceServerProperties();
}
private Filter ssoFilter() {
OAuth2ClientAuthenticationProcessingFilter googleFilter = new OAuth2ClientAuthenticationProcessingFilter("/social_Login"); //해당 경
OAuth2RestTemplate googleTemplate = new OAuth2RestTemplate(googleclient(), oauth2ClientContext);
googleFilter.setRestTemplate(googleTemplate);
googleFilter.setTokenServices(new UserInfoTokenServices(googleResource().getUserInfoUri(), googleclient().getClientId()));
googleFilter.setAuthenticationSuccessHandler(new OAuth2SuccessHandler());
return googleFilter;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(userService.passwordEncoder());
}
}
6. 결과화면
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<!DOCTYPE html>
<html lang="kr">
<head>
<meta charset="UTF-8">
<title>로그인 페이지</title>
</head>
<body>
<h1>로그인</h1>
<hr>
<form action="/login" method="post">
<%-- <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> --%>
<input type="text" name="username" placeholder="이메일 입력해주세요">
<input type="password" name="password" placeholder="비밀번호">
<button type="submit">로그인</button>
</form>
<a href="/social_Login">Login with Google</a>
</body>
</html>
테스트를 위해 간단하게 social_Login으로 요청을 보내는 부분을 추가하였고,
로그인을 진행한뒤
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OauthController {
@RequestMapping(value = "/social_uset_info", method = RequestMethod.GET)
public Object index() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
System.out.println(auth.getDetails());
return auth;
}
}
rest요청으로 해당 정보를 확인해보겠습니다.
다음과 같이 결과가 나오게됩니다.
'Springboot' 카테고리의 다른 글
Springboot security (6) - Oauth2.0 (Google, facebook) 적용 (0) | 2020.03.07 |
---|---|
Springboot security (5) - jwt 적용 (0) | 2020.03.03 |
Springboot security (3) - 권한설정 (0) | 2020.02.26 |
Springboot security (2) - mysql 연동 (0) | 2020.02.26 |
Springboot security (1) - 기본적인 인증과정 (0) | 2020.02.23 |