我有一个spring MVC应用程序和一个远程OAuth2授权服务器。应使用远程服务器登录Web和移动应用程序,并授权微服务。用于授权的OAuth2服务器工作,当我直接调用获取令牌的路径时,该请求会正确返回访问和刷新令牌。
我的问题是我无法在Web应用程序中扩展WebSecurityConfigurerAdapter
的类中配置HttpSecurity,以便使日志记录表单保留在应用程序中并使用密码grunt类型向远程OAuth2发送请求。因此loginProcessingUrl()
不应该是默认j_spring_security_check
,而应该是授权服务器的路径。我在http配置中使用addFilterBefore()
无法实现这一点。
Spring Boot中Oauth2服务器应用程序上的AuthorizationServerConfigurerAdapter
类看起来像这样:
package com.mydomain.oauth2.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenStore tokenStore;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure( AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("acme")
.secret("acmesecret")
.accessTokenValiditySeconds(3600)
.scopes("read", "write")
.redirectUris("http://localhost:8080/login")
.authorizedGrantTypes("password", "refresh_token")
.autoApprove(true)
.resourceIds("resource");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer configurer) throws Exception {
configurer.authenticationManager(authenticationManager);
configurer.userDetailsService(userDetailsService);
configurer.tokenStore(tokenStore);
}
}
我在Spring上编写的不是Spring Boot的Web应用程序的WebSecurityConfigurerAdapter
类看起来像这样:
import java.util.Arrays;
import javax.servlet.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import com.humanbizz.web.security.UserInfoTokenServices;
@Configuration
@EnableWebSecurity
@EnableOAuth2Client
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private OAuth2ClientContextFilter oauth2ClientContextFilter;
@Autowired
OAuth2ClientContext oauth2ClientContext;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login*", "/forgot-password*", "/signup**", "/signup/**", "/resources/**", "/403", "/storage/api/download/**", "/test/public/**").permitAll()
.antMatchers("/user**").anonymous()
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.exceptionHandling()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("?")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/")
.failureUrl("/login?error=true")
.and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.logout().logoutSuccessUrl("/login").deleteCookies("JSESSIONID")
.and()
.addFilterBefore( myFilter(), BasicAuthenticationFilter.class);
}
private Filter myFilter() throws Exception{
OAuth2ClientAuthenticationProcessingFilter myFilter = new OAuth2ClientAuthenticationProcessingFilter("/login");
OAuth2RestTemplate myTemplate = new OAuth2RestTemplate(template(), oauth2ClientContext);
teodeskFilter.setRestTemplate(myTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices("http://localhost:9000/user", "acme");
tokenServices.setRestTemplate(myTemplate);
teodeskFilter.setTokenServices(tokenServices);
return myFilter;
}
@Bean
public OAuth2ProtectedResourceDetails template() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setClientId("acme");
details.setClientSecret("acmesecret");
details.setAccessTokenUri("http://localhost:9000/oauth/token"); details.setUserAuthorizationUri("http://localhost:9000/oauth/authorize");
details.setGrantType("password");
details.setScope(Arrays.asList("read"));
return details;
}
}
我的问题是如何配置过滤器以使用表单和密码grunt类型正确获取令牌。表单位于Web应用程序上,应该向远程auth服务器发出请求。我遇到的示例主要与Spring Boot有关,或者由Authorization Server和Resource Server在同一个应用程序中共同解决。