7

Spring Boot(1.5.2)、Spring Security、Spring Security OAuth2を使用して、Google APIでOAuth2ログインを実装するための小さなプロジェクトをセットアップしました。私はグーグルでの認証とユーザー情報を引き出すことができていますhttps://github.com/ccoloradoc/OAuth2SampleSpring Boot + Spring Security + Spring OAuth2 + Googleログイン

あなたには、ソースを見つけることができます。しかし、ログアウトした後、 ""とRestTemplateを接続してgoogle apiを呼び出そうとすると、 "400 Bad Request"が発生してから再びログインできなくなります。

詳細については、「フィルタを試みる認証方法」を参照してください。

ここに私のセキュリティの設定クラス

@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(); 
    } 

} 

はここに私の認証プロバイダです。

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にそれを翻訳スプリングセキュリティのコアから実装ですそれは春のセキュリティコア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)。最終的には、this was the resourceが私を最も助けました。プロセス全体と統合クライアント側のアプリケーション全体をカバーしていました。

これを下位レベルで実行したい場合は、プロセス全体および多くの詳細がSpringで動作します(Pivotal blog post)。

関連する問題