标签:spring-boot spring-security spring-oauth2 spring spring-mvc
我正在努力用Spring Security配置Spring Boot应用程序以支持两种登录机制:表单登录和Google OAuth2登录.
我想要一个带有传统登录表单的登录页面.该页面上还会有一个“使用Google身份验证按钮”.
登录表单是默认的登录方法,也就是说,当尝试访问受保护的资源时,login.jsp将呈现.用户可以在此处单击oauth按钮.
关键是我可以分别配置它们(表单登录或Google身份验证),但是无法使它们一起工作.
1.-表单登录:
@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
2.- Google身份验证:
@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter{
private final String LOGIN_URL = "/login"
@Autowired
OAuth2ClientContextFilter oAuth2ClientContextFilter
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
return new LoginUrlAuthenticationEntryPoint(LOGIN_URL)
}
@Bean
public OpenIDConnectAuthenticationFilter openIdConnectAuthenticationFilter(){
return new OpenIDConnectAuthenticationFilter(LOGIN_URL)
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(oAuth2ClientContextFilter, AbstractPreAuthenticatedProcessingFilter.class)
.addFilterAfter(openIdConnectAuthenticationFilter(), OAuth2ClientContextFilter.class)
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
.and()
.authorizeRequests()
.anyRequest.authenticated()
}
}
class OpenIDConnectAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
@Resource
private OAuth2RestOperations restTemplate
protected OpenIDConnectAuthenticationFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl)
setAuthenticationManager({authentication -> authentication}) // AbstractAuthenticationProcessingFilter requires an authentication manager.
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
final ResponseEntity<UserInfo> userInfoResponseEntity = restTemplate.getForEntity("https://www.googleapis.com/oauth2/v2/userinfo", UserInfo.class)
new PreAuthenticatedAuthenticationToken(userInfoResponseEntity.getBody(), empty(), NO_AUTHORITIES)
}
}
class UserInfo {
final String id
final String name
final String givenName
final String familyName
final String gender
final String picture
final String link
@JsonCreator
public UserInfo(@JsonProperty("id") String id,
@JsonProperty("name") String name,
@JsonProperty("given_name") String givenName,
@JsonProperty("family_name") String familyName,
@JsonProperty("gender") String gender,
@JsonProperty("picture") String picture,
@JsonProperty("link") String link) {
this.id = id
this.name = name
this.givenName = givenName
this.familyName = familyName
this.gender = gender
this.picture = picture
this.link = link
}
}
@Configuration
@EnableOAuth2Client
class OAuth2Client {
@Value('${google.oauth2.clientId}')
private String clientId
@Value('${google.oauth2.clientSecret}')
private String clientSecret
@Bean
// TODO retrieve from https://accounts.google.com/.well-known/openid-configuration ?
public OAuth2ProtectedResourceDetails googleOAuth2Details() {
AuthorizationCodeResourceDetails googleOAuth2Details = new AuthorizationCodeResourceDetails()
googleOAuth2Details.setAuthenticationScheme(form)
googleOAuth2Details.setClientAuthenticationScheme(form)
googleOAuth2Details.setClientId(clientId)
googleOAuth2Details.setClientSecret(clientSecret)
googleOAuth2Details.setUserAuthorizationUri("https://accounts.google.com/o/oauth2/auth")
googleOAuth2Details.setAccessTokenUri("https://www.googleapis.com/oauth2/v3/token")
googleOAuth2Details.setScope(asList("openid"))
googleOAuth2Details
}
@Resource
private OAuth2ClientContext oAuth2ClientContext
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public OAuth2RestOperations googleOAuth2RestTemplate() {
new OAuth2RestTemplate(googleOAuth2Details(), oAuth2ClientContext)
}
}
class CustomUserDetailsService implements AuthenticationUserDetailsService<OpenIDAuthenticationToken> {
UserDetails loadUserDetails(OpenIDAuthenticationToken token) throws UsernameNotFoundException {
new User(token.name, "", AuthorityUtils.createAuthorityList("ROLE_USER"))
}
}
解决方法:
这就是我使用两个WebSecurityConfigurerAdapters解决它的方式:
@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter{
@Configuration
@Order(1)
static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/secure-home")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
}
}
@Configuration
@Order(2)
static class OAuth2SecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
private final String LOGIN_URL = "/googleLogin";
@Autowired
OAuth2ClientContextFilter oAuth2ClientContextFilter
@Bean
AuthenticationEntryPoint authenticationEntryPoint() {
new LoginUrlAuthenticationEntryPoint(LOGIN_URL)
}
@Bean
OpenIDConnectAuthenticationFilter openIdConnectAuthenticationFilter() {
new OpenIDConnectAuthenticationFilter(LOGIN_URL)
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(oAuth2ClientContextFilter, AbstractPreAuthenticatedProcessingFilter.class)
.addFilterAfter(openIdConnectAuthenticationFilter(), OAuth2ClientContextFilter.class)
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
.and()
.authorizeRequests()
.antMatchers(GET, "/googleOAuth2").authenticated()
}
}
}
完整的源代码在这里:https://github.com/codependent/spring-boot-google-signin
标签:spring-boot,spring-security,spring-oauth2,spring,spring-mvc 来源: https://codeday.me/bug/20191112/2023501.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。