facebook test

This commit is contained in:
liquidjoo
2019-05-23 18:40:32 +09:00
parent 3671ae00cb
commit 0fd06bc576
13 changed files with 314 additions and 64 deletions

View File

@@ -24,6 +24,9 @@ ext {
}
dependencies {
compile('org.springframework.security:spring-security-oauth2-client')
compile('org.springframework.security:spring-security-oauth2-jose')
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-freemarker'
implementation 'org.springframework.boot:spring-boot-starter-web'

View File

@@ -1,16 +1,29 @@
package io.bluemoon.authorizationserver.config;
import io.bluemoon.authorizationserver.domain.social.UserArgumentResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.web.filter.ForwardedHeaderFilter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@EnableWebSecurity
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private UserArgumentResolver userArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(userArgumentResolver);
}
@Bean
FilterRegistrationBean forwardedHeaderFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();

View File

@@ -1,11 +1,6 @@
package io.bluemoon.authorizationserver.config;
import io.bluemoon.authorizationserver.domain.social.ClientResources;
import io.bluemoon.authorizationserver.service.user.CustomUserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
@@ -16,28 +11,18 @@ 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.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.web.filter.CharacterEncodingFilter;
import javax.servlet.Filter;
@Configuration
@EnableWebSecurity
//@Order(SecurityProperties.BASIC_AUTH_ORDER - 6)
@EnableOAuth2Client
@Order(-1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private CustomUserDetailsServiceImpl customUserDetailsService;
@Qualifier("oauth2ClientContext")
@Autowired
private OAuth2ClientContext oAuth2ClientContext;
public WebSecurityConfig(
CustomUserDetailsServiceImpl customUserDetailsService
) {
@@ -63,8 +48,12 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
http
.authorizeRequests()
.antMatchers("/", "/login/**", "/css/**", "/images/**", "/js/**",
"/console/**").permitAll()
"/console/**", "/oauth2/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login()
.defaultSuccessUrl("/loginSuccess")
.failureUrl("/loginFailure")
.and()
.headers().frameOptions().disable()
.and()
@@ -78,8 +67,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.deleteCookies("JSESSSIONID")
.invalidateHttpSession(true)
.and()
.addFilterBefore(filter, CsrfFilter.class)
.csrf().disable();
.addFilterBefore(filter, CsrfFilter.class);
// .csrf().disable();
// http.formLogin().loginPage("/login").permitAll()
// .and()
// .requestMatchers().antMatchers("/login", "/logout", "/oauth/authorize", "/oauth/confirm_access")
@@ -121,12 +110,42 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// social login
@Bean
@ConfigurationProperties("facebook")
public ClientResources facebook() {
return new ClientResources();
}
// @Bean
// public FilterRegistrationBean oauth2ClientFilterRegistration(
// OAuth2ClientContextFilter filter
// ) {
// FilterRegistrationBean registration = new FilterRegistrationBean();
// registration.setFilter(new ForwardedHeaderFilter());
// registration.setFilter(filter);
// registration.setOrder(-100);
// return registration;
// }
//
// private Filter oauth2Filter() {
// CompositeFilter filter = new CompositeFilter();
// List<Filter> filters = new ArrayList<>();
// filters.add(oauth2Filter(facebook(), "/login/facebook", SocialType.FACEBOOK));
//
// filter.setFilters(filters);
// return filter;
// }
//
// private Filter oauth2Filter(ClientResources client, String path, SocialType socialType) {
// OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(path);
// OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oAuth2ClientContext);
// filter.setRestTemplate(template);
// filter.setTokenServices(new UserTokenService(client, socialType));
// filter.setAuthenticationSuccessHandler((request, response, authentication) ->
// response.sendRedirect("/" + socialType.getVaule() + "/complete"));
// filter.setAuthenticationFailureHandler((request, response, exception) ->
// response.sendRedirect("/error"));
// return filter;
// }
//
// @Bean
// @ConfigurationProperties("facebook")
// public ClientResources facebook() {
// return new ClientResources();
// }
}

View File

@@ -0,0 +1,12 @@
package io.bluemoon.authorizationserver.config.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface SocialUser {
}

View File

@@ -1,17 +1,23 @@
package io.bluemoon.authorizationserver.controller.sso;
import io.bluemoon.authorizationserver.config.annotation.SocialUser;
import io.bluemoon.authorizationserver.domain.UserResponseWrapper;
import io.bluemoon.authorizationserver.domain.oauth.accesstoken.AccessToken;
import io.bluemoon.authorizationserver.domain.social.SocialType;
import io.bluemoon.authorizationserver.domain.user.User;
import io.bluemoon.authorizationserver.service.sso.SsoService;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Controller
public class SsoController {
@@ -75,4 +81,34 @@ public class SsoController {
return user;
}
@GetMapping(value = "/loginSuccess")
public String loginComplete(@SocialUser User user) {
return "redirect:/login/success";
}
@GetMapping(value = "/login/success")
@ResponseBody
public String test2() {
return "kkk";
}
// @GetMapping(value = "/{facebook|google|kakao}/complete")
// public String loginComplete(HttpSession session) {
// OAuth2Authentication authentication = (OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication();
// Map<String, String> map = (HashMap<String, String>) authentication.getUserAuthentication().getDetails();
// session.setAttribute("user", User.builder()
// .username(map.get("username"))
// .email(map.get("email"))
// .principal(map.get("id"))
// .socialType(SocialType.FACEBOOK)
// .createdAt(LocalDateTime.now())
// .updatedAt(LocalDateTime.now())
// .build()
// );
// return "redirect:/";
// }
}

View File

@@ -1,22 +1,22 @@
package io.bluemoon.authorizationserver.domain.social;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
public class ClientResources {
@NestedConfigurationProperty
private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
@NestedConfigurationProperty
private ResourceServerProperties resource = new ResourceServerProperties();
public AuthorizationCodeResourceDetails getClient() {
return client;
}
private ResourceServerProperties getResource() {
return resource;
}
}
//package io.bluemoon.authorizationserver.domain.social;
//
//import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
//import org.springframework.boot.context.properties.NestedConfigurationProperty;
//import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
//
//public class ClientResources {
//
// @NestedConfigurationProperty
// private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
//
// @NestedConfigurationProperty
// private ResourceServerProperties resource = new ResourceServerProperties();
//
// public AuthorizationCodeResourceDetails getClient() {
// return client;
// }
//
// public ResourceServerProperties getResource() {
// return resource;
// }
//}

View File

@@ -0,0 +1,127 @@
package io.bluemoon.authorizationserver.domain.social;
import io.bluemoon.authorizationserver.config.annotation.SocialUser;
import io.bluemoon.authorizationserver.domain.user.User;
import io.bluemoon.authorizationserver.domain.user.UserRepository;
import org.springframework.core.MethodParameter;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
private UserRepository userRepository;
public UserArgumentResolver(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterAnnotation(SocialUser.class) != null &&
parameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpSession session = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest().getSession();
User user = (User) session.getAttribute("user");
return getUser(user, session);
}
/**
* 인증된 User 객체를 만드는 메인 메서드
* @param user
* @param session
* @return
*/
private User getUser(User user, HttpSession session) {
// 세션에서 가져온 유저가 널일 경우에만
System.out.println("-------------------------------------");
System.out.println(user);
if (user == null) {
try {
// OAuth2Authentication authentication = (OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication();
// Map<String, String> map = (HashMap<String, String>) authentication.getUserAuthentication().getDetails();
// User convertUser = convertUser(String.valueOf(authentication.getAuthorities().toArray()[0]), map);
OAuth2AuthenticationToken authentication = (OAuth2AuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
Map<String, Object> map = authentication.getPrincipal().getAttributes();
User convertUser = convertUser(authentication.getAuthorizedClientRegistrationId(), map);
user = userRepository.findByEmail(convertUser.getEmail());
if (user == null) {
user = userRepository.save(convertUser);
}
setRoleIfNotSame(user, authentication, map);
session.setAttribute("user", user);
} catch (ClassCastException e) {
return user;
}
}
System.out.println(user);
return user;
}
/**
* 사용자의 인증된 소셜 미디어 타입에 따라 빌더를 사용하여 User 객체를 만들어 주는 가교 역할
* @param authority
* @param map
* @return
*/
private User convertUser(String authority, Map<String, Object> map) {
if (SocialType.FACEBOOK.getVaule().equals(authority)) return getModernUser(SocialType.FACEBOOK, map);
return null;
}
/**
* 페이스북이나 구글 같이 공통되는 명명규칙을 가진 그룹을 맵핑
* @param socialType
* @param map
* @return
*/
private User getModernUser(SocialType socialType, Map<String, Object> map) {
return User.builder()
.username(String.valueOf(map.get("name")))
.email(String.valueOf(map.get("mail")))
.principal(String.valueOf(map.get("id")))
.socialType(socialType)
.createdAt(LocalDateTime.now())
.updatedAt(LocalDateTime.now())
.build();
}
/**
* 인증된 authentication이 권한을 갖고 있는지 체크하는 용도
* 만약 저장된 User 권한이 없으면 SecurityContextHolder를 사용하여 해당 소셜미디어 타입으로 권한을 저장
* @param user
* @param authentication
* @param map
*/
private void setRoleIfNotSame(User user, OAuth2AuthenticationToken authentication, Map<String, Object> map) {
if (!authentication.getAuthorities().contains(
new SimpleGrantedAuthority(user.getSocialType().getRoleType()))) {
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(map, "N/A", AuthorityUtils.createAuthorityList(user.getSocialType().getRoleType()))
);
}
}
}

View File

@@ -0,0 +1,31 @@
//package io.bluemoon.authorizationserver.domain.social;
//
//import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor;
//import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
//import org.springframework.security.core.GrantedAuthority;
//import org.springframework.security.core.authority.AuthorityUtils;
//
//import java.util.List;
//import java.util.Map;
//
//public class UserTokenService extends UserInfoTokenServices {
// public UserTokenService(ClientResources resources, SocialType socialType) {
// super(resources.getResource().getUserInfoUri(), resources.getClient().getClientId());
//
// setAuthoritiesExtractor(new OAuth2AuthoritiesExtractor(socialType));
//
// }
//
// public static class OAuth2AuthoritiesExtractor implements AuthoritiesExtractor {
// private String socialType;
//
// public OAuth2AuthoritiesExtractor(SocialType socialType) {
// this.socialType = socialType.getRoleType();
// }
//
// @Override
// public List<GrantedAuthority> extractAuthorities(Map<String, Object> map) {
// return AuthorityUtils.createAuthorityList(this.socialType);
// }
// }
//}

View File

@@ -21,9 +21,9 @@ public class UserDetail implements UserDetails {
public UserDetail(User user) {
this.id = user.getId();
this.username = user.getUserName();
this.username = user.getUsername();
this.password = user.getPassword();
this.userType = user.getUserType();
// this.userType = user.getSocialType();
}
@Override

View File

@@ -4,5 +4,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByUserName(String userName);
User findByUsername(String username);
User findByEmail(String email);
}

View File

@@ -24,7 +24,7 @@ public class CustomUserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUserName(username);
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("UsernameNotFound[" + username + "]");

View File

@@ -1,5 +1,5 @@
server.port=8081
server.servlet.context-path=/mk-auth
#server.servlet.context-path=/mk-auth
server.use-forward-headers=false
security.oauth2.authorization.check-token-access=isAuthenticated()
@@ -18,12 +18,16 @@ spring.jpa.show-sql=true
#spring.jpa.generate-ddl=false
#spring.jpa.hibernate.ddl-auto=none
facebook.client.client-id=1684497291764010
facebook.client.client-secret=cfefbfbb6ca436828f197df32d85b861
facebook.client.access-token-uri=https://graph.facebook.com/oauth/access_token
facebook.client.user-authorization-uri=https://www.facebook.com/dialog/oauth
facebook.client.token-name=oauth_token
facebook.client.authentication-scheme=query
facebook.client.client-authentication-scheme=form
spring.security.oauth2.client.registration.facebook.client-id=715358882216622
spring.security.oauth2.client.registration.facebook.client-secret=a39d8f1e06e8c3863d12e8461f4991e8
#facebook.client.access-token-uri=https://graph.facebook.com/oauth/access_token
#facebook.client.user-authorization-uri=https://www.facebook.com/dialog/oauth
#facebook.client.token-name=oauth_token
#facebook.client.authentication-scheme=query
#facebook.client.client-authentication-scheme=form
#
#facebook.resource.user-info-uri=https://graph.facebook.com/me?fields=id
facebook.resource.user-info-uri=https://graph.facebook.com/me
logging.level.web=debug
spring.http.log-request-details=true

View File

@@ -16,5 +16,9 @@
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<div>
<a class="facebook-login-text" href="/oauth2/authorization/facebook">facebook으로 로그인</a>
</div>
</body>
</html>