J'ai rendu possible la connexion au serveur API REST créé avec Spring Boot avec Google Sign-In, donc je vais écrire ce que j'ai fait.
La version de Spring Boot que j'utilise est 1.5.7
.
La plupart de ce que vous faites ci-dessous peut être possible avec @ EnableOAuth2Sso
, mais ce n'est pas intéressant, ou c'est tout.
Avant de prendre en charge la connexion à Google, modifiez le comportement par défaut de Spring Security en une ambiance REST.
Site de référence: http://www.baeldung.com/securing-a-restful-web-service-with-spring-security
Dans une application Web standard, si vous accédez à une ressource sécurisée dans un état non authentifié, il vous demandera automatiquement de vous authentifier, mais comme le service REST s'authentifie explicitement, dans ce cas, appuyez simplement sur 401
Il sera retourné.
RestAuthenticationEntryPoint.java
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
Par défaut, lorsque la connexion est réussie, «301» est renvoyé et l'écran est guidé vers l'écran après la connexion, mais dans REST, «200» est simplement renvoyé.
Créez un ʻAuthenticationSuccessHandler qui ne redirige pas en se référant au
SavedRequestAwareAuthenticationSuccessHandler`.
RestSavedRequestAwareAuthenticationSuccessHandler.java
@Component
public class RestSavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private RequestCache requestCache = new HttpSessionRequestCache();
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication) {
SavedRequest savedRequest = requestCache.getRequest(request, response);
if (savedRequest == null) {
clearAuthenticationAttributes(request);
return;
}
String targetUrlParameter = getTargetUrlParameter();
if (isAlwaysUseDefaultTargetUrl()
|| (targetUrlParameter != null && StringUtils.hasText(request
.getParameter(targetUrlParameter)))) {
requestCache.removeRequest(request, response);
clearAuthenticationAttributes(request);
return;
}
clearAuthenticationAttributes(request);
}
}
De même, si la connexion échoue, renvoyez simplement «401».
Vous pouvez utiliser SimpleUrlAuthenticationFailureHandler
de Spring tel quel.
De même, lors de la déconnexion, il ne redirige pas et ne renvoie que «200».
Vous pouvez également utiliser SimpleUrlLogoutSuccessHandler
de Spring ici.
SecurityConfig Créez une configuration dans l'état jusqu'à présent.
SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private RestAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RestSavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private SimpleUrlAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private SimpleUrlLogoutSuccessHandler logoutSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/**").authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.formLogin()
.successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailureHandler)
.and()
.logout()
.logoutSuccessHandler(logoutSuccessHandler)
;
}
@Bean
public SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler() {
return new SimpleUrlAuthenticationFailureHandler();
}
@Bean
public SimpleUrlLogoutSuccessHandler simpleUrlLogoutSuccessHandler() {
return new SimpleUrlLogoutSuccessHandler();
}
}
Enfin le sujet principal.
Coco et Coco -auth) comme référence.
Depuis l'application Web (face avant), ʻid_token qui peut être obtenu lors de la connexion est implémenté dans POST vers
/ loginavec
x-www-form-urlencoded`.
Le nom du paramètre est «google_id_token».
Intégrez formLogin ()
au SecurityConfig # configure (HttpSecurity http)
créé comme suit.
SecurityConfig.java
.formLogin()
.passwordParameter("google_id_token")
.successHandler(authenticationSuccessHandler)
Je viens d'ajouter passwordParameter (" google_id_token ")
.
Vous recevrez maintenant ʻid_token` comme mot de passe pour l'authentification avec votre nom d'utilisateur et votre mot de passe par défaut.
Maintenant que vous avez reçu ʻid_token`, il ne vous reste plus qu'à implémenter l'authentification.
GoogleIdAuthenticationProvider.java
@Component
public class GoogleIdAuthenticationProvider implements AuthenticationProvider {
private final String clientId = "XXX.apps.googleusercontent.com";
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String tokenString = (String) authentication.getCredentials();
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(UrlFetchTransport.getDefaultInstance(), JacksonFactory.getDefaultInstance())
.setAudience(singletonList(clientId))
.build();
GoogleIdToken idToken;
try {
idToken = verifier.verify(tokenString);
if (idToken == null) {
throw new BadCredentialsException("Failed to verify token");
}
} catch (GeneralSecurityException|IOException e) {
throw new AuthenticationServiceException("Failed to verify token", e);
}
GoogleIdToken.Payload payload = idToken.getPayload();
String userId = payload.getSubject();
String name = (String) payload.get("name");
GoogleUser user = new GoogleUser(userId, name);
List<GrantedAuthority> authorities = singletonList(new SimpleGrantedAuthority("ROLE_USER"));
return new UsernamePasswordAuthenticationToken(user, tokenString, authorities);
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.equals(authentication);
}
}
Si vous voulez vous limiter à un domaine spécifique, vous pouvez le faire en cochant payload.getHostedDomain ()
.
La classe «GoogleUser» est la suivante.
GoogleUser.java
@Data
@RequiredArgsConstructor
@AllArgsConstructor
public class GoogleUser implements UserDetails {
@NotNull
@Setter(AccessLevel.NONE)
private String userId;
private String username;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return null;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
}
Vous êtes maintenant prêt pour la connexion à Google.
Recommended Posts