7

스프링 부트 (1.5.2), 스프링 보안 및 스프링 보안 OAuth2를 사용하여 Google+ API로 OAuth2 로그인을 구현하는 작은 프로젝트를 설정했습니다. 내가 구글 인증 및 사용자 정보를 당길 수 있어요 https://github.com/ccoloradoc/OAuth2Sample스프링 부트 + 스프링 보안 + 스프링 OAuth2 + Google 로그인

:

당신은에서 소스를 찾을 수 있습니다. 그러나 로그 아웃 한 후 RestTemplate에 "https://accounts.google.com/o/oauth2/auth"을 연결하여 Google api를 호출 한 후에 "400 Bad Request"를 얻었으므로 다시 로그인 할 수 없습니다.

자세한 내용은 필터 시도 인증 방법을 참조하십시오.

public class GoogleOauth2AuthProvider implements AuthenticationProvider { 

    private static final Logger logger = LoggerFactory.getLogger(GoogleOauth2AuthProvider.class); 

    @Autowired(required = true) 
    private UserDetailsService userDetailsService; 

    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
     logger.info("Provider Manager Executed"); 
     CustomOAuth2AuthenticationToken token = (CustomOAuth2AuthenticationToken) authentication; 
     UserDetailsImpl registeredUser = (UserDetailsImpl) token.getPrincipal(); 
     try { 
      registeredUser = (UserDetailsImpl) userDetailsService 
        .loadUserByUsername(registeredUser.getEmail()); 
     } catch (UsernameNotFoundException usernameNotFoundException) { 
      logger.info("User trying google/login not already a registered user. Register Him !!"); 
     } 
     return token; 
    } 

    @Override 
    public boolean supports(Class<?> authentication) { 
     return CustomOAuth2AuthenticationToken.class 
       .isAssignableFrom(authentication); 
    } 
} 

UserDetailService 데이터베이스에서 사용자를 읽고 된 UserDetails의 POJO로 번역 봄 보안 코어에서 구현 한 것입니다 : 여기

여기
@Configuration 
@EnableGlobalAuthentication 
@EnableOAuth2Client 
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) 
@PropertySource(value = {"classpath:oauth.properties"}) 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 


    @Autowired 
    private UserDetailsService userDetailsService; 

    @Resource 
    @Qualifier("accessTokenRequest") 
    private AccessTokenRequest accessTokenRequest; 

    @Autowired 
    private OAuth2ClientContextFilter oAuth2ClientContextFilter; 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     // @formatter:off 
     http. 
       authorizeRequests() 
       .antMatchers(HttpMethod.GET, "/login","/public/**", "/resources/**","/resources/public/**").permitAll() 
       .antMatchers("/google_oauth2_login").anonymous() 
       .anyRequest().authenticated() 
       .and() 
       .formLogin() 
       .loginPage("/login") 
       .loginProcessingUrl("/login") 
       .defaultSuccessUrl("/") 
       .and() 
       .csrf().disable() 
       .logout() 
       .logoutSuccessUrl("/") 
       .logoutUrl("/logout") 
       .deleteCookies("remember-me") 
       .and() 
       .rememberMe() 
       .and() 
       .addFilterAfter(oAuth2ClientContextFilter,ExceptionTranslationFilter.class) 
       .addFilterAfter(googleOAuth2Filter(),OAuth2ClientContextFilter.class) 
       .userDetailsService(userDetailsService); 
     // @formatter:on 
    } 

    @Bean 
    @ConfigurationProperties("google.client") 
    public OAuth2ProtectedResourceDetails auth2ProtectedResourceDetails() { 
     return new AuthorizationCodeResourceDetails(); 
    } 

    @Bean 
    public OAuth2RestTemplate oauth2RestTemplate() { 
     return new OAuth2RestTemplate(auth2ProtectedResourceDetails(), 
       new DefaultOAuth2ClientContext(accessTokenRequest)); 
    } 


    @Bean 
    public GoogleOAuth2Filter googleOAuth2Filter() { 
     return new GoogleOAuth2Filter("/google_oauth2_login"); 
    } 

    /* 
    * Building our custom Google Provider 
    * */ 
    @Bean 
    public GoogleOauth2AuthProvider googleOauth2AuthProvider() { 
     return new GoogleOauth2AuthProvider(); 
    } 

    /* 
    * Using autowired to assign it to the auth manager 
    * */ 
    @Autowired 
    public void configureGlobal(AuthenticationManagerBuilder auth) { 
     auth.authenticationProvider(googleOauth2AuthProvider()); 
    } 

    @Bean 
    public SpringSecurityDialect springSecurityDialect() { 
     return new SpringSecurityDialect(); 
    } 

    @Bean 
    public TokenStore tokenStore() { 
     return new InMemoryTokenStore(); 
    } 

} 

내 인증 공급자 내 보안 구성 클래스입니다 스프링 보안 핵심 UserDetails를 구현합니다. (당신의 절차를 많이 숨 깁니다하지만) 당신은 EnableOAuth2Sso 방법을 사용하는 경우

public class GoogleOAuth2Filter extends AbstractAuthenticationProcessingFilter { 

    /** 
    * Logger 
    */ 
    private static final Logger log = LoggerFactory.getLogger(GoogleOAuth2Filter.class); 

    private static final Authentication dummyAuthentication; 

    static { 
     dummyAuthentication = new UsernamePasswordAuthenticationToken(
       "dummyUserName23452346789", "dummyPassword54245", 
       CustomUserDetails.DEFAULT_ROLES); 
    } 

    private static final String NAME = "name"; 
    private static final String EMAIL = "email"; 
    private static final String PICTURE = "picture"; 

    private static final Logger logger = LoggerFactory 
      .getLogger(GoogleOAuth2Filter.class); 


    @Value(value = "${google.authorization.url}") 
    private String googleAuhorizationUrl; 

    public GoogleOAuth2Filter(String defaultFilterProcessesUrl) { 
     super(defaultFilterProcessesUrl); 
    } 

    @Autowired 
    private UserService userService; 

    @Autowired 
    private OAuth2RestTemplate oauth2RestTemplate; 

    @Autowired 
    @Override 
    public void setAuthenticationManager(AuthenticationManager authenticationManager) { 
     super.setAuthenticationManager(authenticationManager); 
    } 

    @Override 
    public Authentication attemptAuthentication(HttpServletRequest request, 
               HttpServletResponse response) throws AuthenticationException, 
      IOException, ServletException { 
     logger.info("Google Oauth Filter Triggered!!"); 
     URI authURI; 
     try { 
      authURI = new URI(googleAuhorizationUrl); 
     } catch (URISyntaxException e) { 
      log.error("\n\n\n\nERROR WHILE CREATING GOOGLE AUTH URL", e); 
      return null; 
     } 
     SecurityContext context = SecurityContextHolder.getContext(); 
     // auth null or not authenticated. 
     String code = request.getParameter("code"); 
     Map<String, String[]> parameterMap = request.getParameterMap(); 
     logger.debug(parameterMap.toString()); 
     if (StringUtils.isEmpty(code)) { 
      // Google authentication in progress. will return null. 
      logger.debug("Will set dummy user in context "); 
      context.setAuthentication(dummyAuthentication); 
      // trigger google oauth2. 
      // ERROR ON SECOND LOGIN ATTEMPT 
      oauth2RestTemplate.postForEntity(authURI, null, Object.class); 
      return null; 
     } else { 
      logger.debug("Response from Google Recieved !!"); 

      ResponseEntity<Object> forEntity = oauth2RestTemplate.getForEntity(
        "https://www.googleapis.com/plus/v1/people/me/openIdConnect", 
        Object.class); 

      @SuppressWarnings("unchecked") 
      Map<String, String> profile = (Map<String, String>) forEntity.getBody(); 

      CustomOAuth2AuthenticationToken authenticationToken = getOAuth2Token(
        profile.get(EMAIL), profile.get(NAME), profile.get(PICTURE)); 
      authenticationToken.setAuthenticated(false); 

      return getAuthenticationManager().authenticate(authenticationToken); 
     } 
    } 

    private CustomOAuth2AuthenticationToken getOAuth2Token(
      String email, String name, String picture) { 

     User user = userService.findByEmail(email); 
     //Register user 
     if(user == null) { 
      user = new User(name, email, picture); 
      userService.saveOrUpdate(user); 
     } 

     UserDetailsImpl registeredUser = new UserDetailsImpl(name, email, picture); 

     CustomOAuth2AuthenticationToken authenticationToken = 
       new CustomOAuth2AuthenticationToken(registeredUser); 

     return authenticationToken; 
    } 

} 

답변

3

상황이 훨씬 더 쉽게 얻을 :

여기 내 필터의 구현입니다. The Spring Boot tutorial on OAuth2은 이것에 대해 매우 철저합니다. 온라인에서 인용 한 다른 예가 있습니다 (예 : https://github.com/SoatGroup/spring-boot-google-auth/http://dreamix.eu/blog/java/configuring-google-as-oauth2-authorization-provider-in-spring-boot). 조금 도움이되었습니다. 궁극적으로 전체 프로세스 및 통합 클라이언트 측 응용 프로그램을 가장 잘 이해하는 데 도움이 된 입니다.

하위 단계에서이 작업을 수행하려는 경우 전체 프로세스에 대한 많은 세부 사항과 Pivotal blog post에서 Spring에서 작동하는 방법이 있습니다.