Ich habe es möglich gemacht, mich bei dem mit Spring Boot mit Google Sign-In erstellten REST-API-Server anzumelden, damit ich aufschreiben kann, was ich getan habe.
Die Version von Spring Boot, die ich verwende, ist "1.5.7".
Das meiste, was Sie unten tun, ist möglicherweise mit @ EnableOAuth2Sso
möglich, aber das ist nicht interessant oder das war's.
Ändern Sie vor der Unterstützung von Google Sign-In das Standardverhalten von Spring Security in ein REST-Verhalten.
Referenzseite: http://www.baeldung.com/securing-a-restful-web-service-with-spring-security
Wenn Sie in einer Standard-Webanwendung in einem nicht authentifizierten Zustand auf eine sichere Ressource zugreifen, werden Sie automatisch zur Authentifizierung aufgefordert. Da sich der REST-Service jedoch explizit authentifiziert, drücken Sie in einem solchen Fall einfach "401". Es wird zurückgegeben.
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");
}
}
Wenn die Anmeldung erfolgreich ist, wird standardmäßig "301" zurückgegeben und der Bildschirm wird nach der Anmeldung zum Bildschirm geführt. In REST wird "200" jedoch einfach zurückgegeben. Erstellen Sie einen "AuthenticationSuccessHandler", der nicht umleitet, indem Sie auf den "SavedRequestAwareAuthenticationSuccessHandler" verweisen.
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);
}
}
Wenn die Anmeldung fehlschlägt, geben Sie einfach "401" zurück. Sie können den SimpleUrlAuthenticationFailureHandler von Spring so wie er ist verwenden.
In ähnlicher Weise wird beim Abmelden nicht umgeleitet und nur "200" zurückgegeben.
Sie können hier auch den SimpleUrlLogoutSuccessHandler
von Spring verwenden.
SecurityConfig Erstellen Sie eine Konfiguration im bisherigen Status.
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();
}
}
Endlich das Hauptthema. Coco und Coco -auth) als Referenz. Von der Webanwendung (Vorderseite) wird das "id_token", das bei der Anmeldung abgerufen werden kann, in POST to "/ login" mit "x-www-form-urlencoded" implementiert. Der Parametername lautet "google_id_token".
Machen Sie den formLogin ()
Teil der erstelltenSecurityConfig # configure (HttpSecurity http)
wie folgt.
SecurityConfig.java
.formLogin()
.passwordParameter("google_id_token")
.successHandler(authenticationSuccessHandler)
Ich habe gerade passwordParameter (" google_id_token ")
hinzugefügt.
Sie erhalten nun "id_token" als Passwort für die Authentifizierung mit Ihrem Standardbenutzernamen und -passwort.
AuthenticationProvider
Nachdem Sie das "id_token" erhalten haben, müssen Sie nur noch die Authentifizierung implementieren.
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);
}
}
Wenn Sie sich auf eine bestimmte Domain beschränken möchten, können Sie dies tun, indem Sie "payload.getHostedDomain ()" aktivieren.
Die GoogleUser-Klasse lautet wie folgt.
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;
}
}
Sie sind jetzt bereit für die Google-Anmeldung.
Recommended Posts