我已经设置了一个小项目,使用Spring Boot(1.5.2),Spring Security和Spring Security OAuth2实施OAuth2使用Google+ API登录.
您可以在以下网址找到来源:https://github.com/ccoloradoc/OAuth2Sample
我可以通过谷歌进行身份验证并提取用户信息.但是,在我注销后,由于我尝试将" https://accounts.google.com/o/oauth2/auth "与我的RestTemplate 连接以调用google api ,因此我收到"400 Bad Request"后无法再次登录.
有关进一步参考,请参阅Filter attemptAuthentication方法.
这是我的安全配置类
@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是Spring安全核心的一个实现,它从数据库读取用户并将其转换为实现Spring安全核心UserDetails的UserDetails POJO.
这是我的过滤器实现:
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"); MapparameterMap = 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
HFR1994.. 6
谢谢克里斯蒂安,您不知道您的代码为我自己的代码奠定了基础。我修改了原始的OAuth2 Github项目,并将其更改为以下代码。
GoogleOAuth2Filter.java
package tech.aabo.celulascontentas.oauth.filter; import static java.lang.Math.toIntExact; import com.google.api.client.auth.oauth2.AuthorizationCodeResponseUrl; import com.google.api.client.auth.oauth2.TokenResponse; import com.google.api.client.auth.oauth2.TokenResponseException; import com.google.api.client.googleapis.auth.oauth2.*; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.services.plus.Plus; import com.google.api.services.plus.model.Person; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.configurationprocessor.json.JSONException; import org.springframework.boot.configurationprocessor.json.JSONObject; import org.springframework.core.io.ClassPathResource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import tech.aabo.celulascontentas.oauth.domain.User; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.math.BigInteger; import java.sql.Timestamp; import java.time.Instant; import java.util.Arrays; import java.util.Calendar; import java.util.UUID; /** * Created by colorado on 9/03/17. * Modified by frhec on 7/06/18 */ public class GoogleOAuth2Filter extends AbstractAuthenticationProcessingFilter { /** * Logger */ private static final Logger logger = LoggerFactory.getLogger(GoogleOAuth2Filter.class); public GoogleOAuth2Filter(String defaultFilterProcessesUrl) { super(defaultFilterProcessesUrl); } @Autowired @Override public void setAuthenticationManager(AuthenticationManager authenticationManager) { super.setAuthenticationManager(authenticationManager); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { String CLIENT_SECRET_FILE = "client_secret.json"; SecurityContext context = SecurityContextHolder.getContext(); if(context.getAuthentication() == null) { GoogleClientSecrets clientSecrets = loadSecret(CLIENT_SECRET_FILE); if (StringUtils.isEmpty(request.getQueryString())) { try { GoogleAuthorizationCodeRequestUrl auth = new GoogleAuthorizationCodeRequestUrl(clientSecrets.getDetails().getClientId(), request.getRequestURL().toString(), Arrays.asList( "https://www.googleapis.com/auth/plus.login", "https://www.googleapis.com/auth/plus.me", "https://www.googleapis.com/auth/plus.profile.emails.read")).setState("/user"); auth.setAccessType("offline"); response.addHeader("Place","Before"); response.sendRedirect(auth.build()); } catch (IOException e) { e.printStackTrace(); } } else { response.addHeader("Place","After"); AuthorizationCodeResponseUrl authResponse = new AuthorizationCodeResponseUrl(transformName(request, 0)); // check for user-denied error if (authResponse.getError() != null) { logger.info("Denied"); } else { try { assert clientSecrets != null; Calendar calendar = Calendar.getInstance(); NetHttpTransport net = new NetHttpTransport(); JacksonFactory jackson = new JacksonFactory(); GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(net, jackson, clientSecrets.getDetails().getClientId(), clientSecrets.getDetails().getClientSecret(), authResponse.getCode(), transformName(request, 1)) .execute(); // Use access token to call API GoogleCredential credential; if (tokenResponse.getRefreshToken() == null) { credential = new GoogleCredential(); credential.setFromTokenResponse(tokenResponse); } else { credential = createCredentialWithRefreshToken(net, jackson, clientSecrets, tokenResponse); } Plus plus = new Plus.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential) .setApplicationName("Google Plus Profile Info") .build(); Person profile = plus.people().get("me").execute(); // Get profile info from ID token GoogleIdToken idToken = tokenResponse.parseIdToken(); GoogleIdToken.Payload payload = idToken.getPayload(); User auth = new User(); auth.setAccessToken(tokenResponse.getAccessToken()); auth.setId(new BigInteger(payload.getSubject().trim())); // Use this value as a key to identify a user. auth.setUuid(UUID.randomUUID().toString()); auth.setEmail(payload.getEmail()); auth.setVerifiedEmail(payload.getEmailVerified()); auth.setName(profile.getDisplayName()); auth.setPictureURL(profile.getImage().getUrl()); auth.setLocale(profile.getLanguage()); auth.setFamilyName(profile.getName().getFamilyName()); auth.setGivenName(profile.getName().getGivenName()); auth.setStatus(true); auth.setExpired(false); auth.setLocked(false); auth.setExpiredCredentials(false); auth.setRoles("USER"); auth.setRefreshToken(tokenResponse.getRefreshToken()); auth.setDateCreated(calendar.getTime()); calendar.add(Calendar.SECOND, toIntExact(tokenResponse.getExpiresInSeconds())); auth.setExpirationDate(calendar.getTime()); auth.setDateModified(Calendar.getInstance().getTime()); Authentication authenticationToken = getOAuth2Token(auth); request.authenticate(response); if (//Validation happening) { authenticationToken.setAuthenticated(true); } else { authenticationToken.setAuthenticated(false); } return authenticationToken; } catch (TokenResponseException e) { if (e.getDetails() != null) { System.err.println("Error: " + e.getDetails().getError()); if (e.getDetails().getErrorDescription() != null) { System.err.println(e.getDetails().getErrorDescription()); } if (e.getDetails().getErrorUri() != null) { System.err.println(e.getDetails().getErrorUri()); } } else { System.err.println(e.getMessage()); } } catch (IOException | ServletException e) { e.printStackTrace(); } } } }else if(!context.getAuthentication().isAuthenticated()) { setResponseUnauthenticated(response); }else{ try { response.sendRedirect(transformName(request,2)+"/user"); } catch (IOException e) { e.printStackTrace(); } } return null; } private void setResponseUnauthenticated(HttpServletResponse response){ try { response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); //create Json Object JSONObject values = new JSONObject(); values.put("principal", null); values.put("authentication", null); values.put("timestamp", String.valueOf(Timestamp.from(Instant.now()))); values.put("code",401); values.put("message", "Not Authorized"); out.print(values.toString()); } catch (JSONException | IOException e) { e.printStackTrace(); } } public static GoogleCredential createCredentialWithRefreshToken(HttpTransport transport, JsonFactory jsonFactory, GoogleClientSecrets clientSecrets, TokenResponse tokenResponse) { return new GoogleCredential.Builder().setTransport(transport) .setJsonFactory(jsonFactory) .setClientSecrets(clientSecrets) .build() .setFromTokenResponse(tokenResponse); } public static String transformName(HttpServletRequest request, Integer type){ switch(type) { case 0: return request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort() + // "8080" request.getRequestURI() + // "/people" "?" + // "?" request.getQueryString(); // "lastname=Fox&age=30" case 1: return request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort() + // "8080" request.getRequestURI(); // "/people" case 2: return request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort(); // "8080" default: return request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort() + // "8080" request.getRequestURI() + // "/people" "?" + // "?" request.getQueryString(); // "lastname=Fox&age=30" } } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { SecurityContextHolder.getContext().setAuthentication(authResult); // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent( authResult, this.getClass())); } response.sendRedirect(transformName(request,2)+"/user"); } private CustomOAuth2AuthenticationToken getOAuth2Token(User auth) { return new CustomOAuth2AuthenticationToken(auth); } private GoogleClientSecrets loadSecret(String name){ ClassPathResource resource = new ClassPathResource(name); try { // Exchange auth code for access token return GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(), new FileReader(resource.getFile())); } catch (IOException e) { return null; } } }
另外,我将主要的Security类更改为:
private GoogleOAuth2Filter googleOAuth2Filter = new GoogleOAuth2Filter("/login/google"); @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.antMatcher("/**") .authorizeRequests() .antMatchers("/", "/login/google", "/error**").permitAll().anyRequest().authenticated() .and().exceptionHandling().authenticationEntryPoint((request, response, e) -> { //create Json Object try { JSONObject values = new JSONObject(); values.put("principal", JSONObject.NULL); values.put("authentication", JSONObject.NULL); values.put("timestamp", String.valueOf(Timestamp.from(Instant.now()))); values.put("code",401); values.put("message", "Not Authorized"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(values.toString()); } catch (JSONException | IOException f) { f.printStackTrace(); } }) .and().addFilterBefore(googleOAuth2Filter, BasicAuthenticationFilter.class); // @formatter:on }
我还为/ user和/ logout创建了自定义映射。
希望它将来能对某人有所帮助
谢谢克里斯蒂安,您不知道您的代码为我自己的代码奠定了基础。我修改了原始的OAuth2 Github项目,并将其更改为以下代码。
GoogleOAuth2Filter.java
package tech.aabo.celulascontentas.oauth.filter; import static java.lang.Math.toIntExact; import com.google.api.client.auth.oauth2.AuthorizationCodeResponseUrl; import com.google.api.client.auth.oauth2.TokenResponse; import com.google.api.client.auth.oauth2.TokenResponseException; import com.google.api.client.googleapis.auth.oauth2.*; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.services.plus.Plus; import com.google.api.services.plus.model.Person; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.configurationprocessor.json.JSONException; import org.springframework.boot.configurationprocessor.json.JSONObject; import org.springframework.core.io.ClassPathResource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import tech.aabo.celulascontentas.oauth.domain.User; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.math.BigInteger; import java.sql.Timestamp; import java.time.Instant; import java.util.Arrays; import java.util.Calendar; import java.util.UUID; /** * Created by colorado on 9/03/17. * Modified by frhec on 7/06/18 */ public class GoogleOAuth2Filter extends AbstractAuthenticationProcessingFilter { /** * Logger */ private static final Logger logger = LoggerFactory.getLogger(GoogleOAuth2Filter.class); public GoogleOAuth2Filter(String defaultFilterProcessesUrl) { super(defaultFilterProcessesUrl); } @Autowired @Override public void setAuthenticationManager(AuthenticationManager authenticationManager) { super.setAuthenticationManager(authenticationManager); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { String CLIENT_SECRET_FILE = "client_secret.json"; SecurityContext context = SecurityContextHolder.getContext(); if(context.getAuthentication() == null) { GoogleClientSecrets clientSecrets = loadSecret(CLIENT_SECRET_FILE); if (StringUtils.isEmpty(request.getQueryString())) { try { GoogleAuthorizationCodeRequestUrl auth = new GoogleAuthorizationCodeRequestUrl(clientSecrets.getDetails().getClientId(), request.getRequestURL().toString(), Arrays.asList( "https://www.googleapis.com/auth/plus.login", "https://www.googleapis.com/auth/plus.me", "https://www.googleapis.com/auth/plus.profile.emails.read")).setState("/user"); auth.setAccessType("offline"); response.addHeader("Place","Before"); response.sendRedirect(auth.build()); } catch (IOException e) { e.printStackTrace(); } } else { response.addHeader("Place","After"); AuthorizationCodeResponseUrl authResponse = new AuthorizationCodeResponseUrl(transformName(request, 0)); // check for user-denied error if (authResponse.getError() != null) { logger.info("Denied"); } else { try { assert clientSecrets != null; Calendar calendar = Calendar.getInstance(); NetHttpTransport net = new NetHttpTransport(); JacksonFactory jackson = new JacksonFactory(); GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(net, jackson, clientSecrets.getDetails().getClientId(), clientSecrets.getDetails().getClientSecret(), authResponse.getCode(), transformName(request, 1)) .execute(); // Use access token to call API GoogleCredential credential; if (tokenResponse.getRefreshToken() == null) { credential = new GoogleCredential(); credential.setFromTokenResponse(tokenResponse); } else { credential = createCredentialWithRefreshToken(net, jackson, clientSecrets, tokenResponse); } Plus plus = new Plus.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential) .setApplicationName("Google Plus Profile Info") .build(); Person profile = plus.people().get("me").execute(); // Get profile info from ID token GoogleIdToken idToken = tokenResponse.parseIdToken(); GoogleIdToken.Payload payload = idToken.getPayload(); User auth = new User(); auth.setAccessToken(tokenResponse.getAccessToken()); auth.setId(new BigInteger(payload.getSubject().trim())); // Use this value as a key to identify a user. auth.setUuid(UUID.randomUUID().toString()); auth.setEmail(payload.getEmail()); auth.setVerifiedEmail(payload.getEmailVerified()); auth.setName(profile.getDisplayName()); auth.setPictureURL(profile.getImage().getUrl()); auth.setLocale(profile.getLanguage()); auth.setFamilyName(profile.getName().getFamilyName()); auth.setGivenName(profile.getName().getGivenName()); auth.setStatus(true); auth.setExpired(false); auth.setLocked(false); auth.setExpiredCredentials(false); auth.setRoles("USER"); auth.setRefreshToken(tokenResponse.getRefreshToken()); auth.setDateCreated(calendar.getTime()); calendar.add(Calendar.SECOND, toIntExact(tokenResponse.getExpiresInSeconds())); auth.setExpirationDate(calendar.getTime()); auth.setDateModified(Calendar.getInstance().getTime()); Authentication authenticationToken = getOAuth2Token(auth); request.authenticate(response); if (//Validation happening) { authenticationToken.setAuthenticated(true); } else { authenticationToken.setAuthenticated(false); } return authenticationToken; } catch (TokenResponseException e) { if (e.getDetails() != null) { System.err.println("Error: " + e.getDetails().getError()); if (e.getDetails().getErrorDescription() != null) { System.err.println(e.getDetails().getErrorDescription()); } if (e.getDetails().getErrorUri() != null) { System.err.println(e.getDetails().getErrorUri()); } } else { System.err.println(e.getMessage()); } } catch (IOException | ServletException e) { e.printStackTrace(); } } } }else if(!context.getAuthentication().isAuthenticated()) { setResponseUnauthenticated(response); }else{ try { response.sendRedirect(transformName(request,2)+"/user"); } catch (IOException e) { e.printStackTrace(); } } return null; } private void setResponseUnauthenticated(HttpServletResponse response){ try { response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); //create Json Object JSONObject values = new JSONObject(); values.put("principal", null); values.put("authentication", null); values.put("timestamp", String.valueOf(Timestamp.from(Instant.now()))); values.put("code",401); values.put("message", "Not Authorized"); out.print(values.toString()); } catch (JSONException | IOException e) { e.printStackTrace(); } } public static GoogleCredential createCredentialWithRefreshToken(HttpTransport transport, JsonFactory jsonFactory, GoogleClientSecrets clientSecrets, TokenResponse tokenResponse) { return new GoogleCredential.Builder().setTransport(transport) .setJsonFactory(jsonFactory) .setClientSecrets(clientSecrets) .build() .setFromTokenResponse(tokenResponse); } public static String transformName(HttpServletRequest request, Integer type){ switch(type) { case 0: return request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort() + // "8080" request.getRequestURI() + // "/people" "?" + // "?" request.getQueryString(); // "lastname=Fox&age=30" case 1: return request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort() + // "8080" request.getRequestURI(); // "/people" case 2: return request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort(); // "8080" default: return request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort() + // "8080" request.getRequestURI() + // "/people" "?" + // "?" request.getQueryString(); // "lastname=Fox&age=30" } } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { SecurityContextHolder.getContext().setAuthentication(authResult); // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent( authResult, this.getClass())); } response.sendRedirect(transformName(request,2)+"/user"); } private CustomOAuth2AuthenticationToken getOAuth2Token(User auth) { return new CustomOAuth2AuthenticationToken(auth); } private GoogleClientSecrets loadSecret(String name){ ClassPathResource resource = new ClassPathResource(name); try { // Exchange auth code for access token return GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(), new FileReader(resource.getFile())); } catch (IOException e) { return null; } } }
另外,我将主要的Security类更改为:
private GoogleOAuth2Filter googleOAuth2Filter = new GoogleOAuth2Filter("/login/google"); @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.antMatcher("/**") .authorizeRequests() .antMatchers("/", "/login/google", "/error**").permitAll().anyRequest().authenticated() .and().exceptionHandling().authenticationEntryPoint((request, response, e) -> { //create Json Object try { JSONObject values = new JSONObject(); values.put("principal", JSONObject.NULL); values.put("authentication", JSONObject.NULL); values.put("timestamp", String.valueOf(Timestamp.from(Instant.now()))); values.put("code",401); values.put("message", "Not Authorized"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(values.toString()); } catch (JSONException | IOException f) { f.printStackTrace(); } }) .and().addFilterBefore(googleOAuth2Filter, BasicAuthenticationFilter.class); // @formatter:on }
我还为/ user和/ logout创建了自定义映射。
希望它将来能对某人有所帮助
如果使用该EnableOAuth2Sso
方法,事情会变得容易得多(尽管它对您隐藏了很多过程)。关于OAuth2的Spring Boot教程对此非常详尽,还有其他一些我从中抄袭的示例(例如https://github.com/SoatGroup/spring-boot-google-auth/和http://dreamix.eu / blog / java / configuring-google-as-oauth2-authorization-provider-in-spring-boot)有所帮助。最终,这是对我帮助最大的资源 -涵盖了整个过程和集成客户端应用程序。
如果您想在较低级别进行此操作,请参阅Pivotal博客文章,其中有很多有关整个过程及其在Spring中如何工作的详细信息。