with secure mkyong google example auth and spring spring-security google-api spring-security-oauth2

secure - spring boot oauth2



Spring Boot+Spring Security+Spring OAuth2+Google Iniciar sesiĆ³n (1)

He configurado un pequeño proyecto para implementar el inicio de sesión de OAuth2 con la API de Google+, utilizando Spring Boot (1.5.2), Spring Security y Spring Security OAuth2.

Puede encontrar la fuente en: https://github.com/ccoloradoc/OAuth2Sample

Puedo autenticarme con google y extraer información del usuario. Sin embargo, después de cerrar la sesión, no puedo volver a iniciar sesión desde que recibí una "400 Solicitud incorrecta", después de intentar conectar " https://accounts.google.com/o/oauth2/auth " con mi RestTemplate para invocar google api.

Ver el método de prueba de intento de filtro para mayor referencia.

Aquí está mi clase de configuración de seguridad

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

Aquí está mi proveedor de autenticación:

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 es una implementación del núcleo de seguridad de primavera que lee al usuario de la base de datos y lo traduce a un POJO UserDetails que implementa el núcleo de seguridad de primavera UserDetails.

Aquí está mi implementación de filtro:

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; } }


Las cosas se vuelven mucho más fáciles si usas el método EnableOAuth2Sso (aunque oculta mucho del proceso). El tutorial de Spring Boot en OAuth2 es bastante completo para esto, y hay otros ejemplos en línea de los que he extraído (por ejemplo, https://github.com/SoatGroup/spring-boot-google-auth/ y http://dreamix.eu / blog / java / configuring-google-as-oauth2-authorization-provider-in-spring-boot ) que ayudó un poco. En última instancia, este fue el recurso que más me ayudó: abarcar todo el proceso y las aplicaciones integradas del lado del cliente.

Si desea hacer esto en un nivel inferior, hay muchos detalles sobre todo el proceso y cómo funciona en Spring en una publicación de blog de Pivotal .