我正在使用openid的授权代码流与springboot连接。 我在本地主机上运行2服务。一个托管受保护资源,另一个是客户端。他们现在在同一个项目中,因为这只是概念的证明。
当用户尝试访问主页时,我想将他们重定向到我们的自定义登录页面。授权后,我要允许他们访问受保护的资源
我的客户端配置:
@Configuration
@EnableOAuth2Client
@EnableWebSecurity
@ComponentScan("com.myclient”)
@Profile({"dev"})
public class OpenIdConnectClientConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**").authorizeRequests()
.antMatchers("/login**", “/##/token.oauth2", “/##/authorization.oauth2").permitAll()
.and()
.anonymous().disable()
.logout()
.permitAll()
.deleteCookies("remove")
.clearAuthentication(true)
.invalidateHttpSession(true)
.logoutSuccessUrl("https://mylogout/logout")
.and().httpBasic().disable();
}// @formatter:on
@Override
public void configure(WebSecurity web) throws Exception {// @formatter:off
web
.ignoring()
.mvcMatchers(
"/favicon.ico",
"/webjars/**",
"/css/**");
}// @formatter:on
// thymeleaf
@Bean
public ClassLoaderTemplateResolver templateResolver() {
final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}
@Bean
public ThymeleafViewResolver viewResolver() {
final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
return viewResolver;
}
// end thymeleaf
@Configuration
@EnableOAuth2Client
protected static class OAuthClientConfig {
@Bean
public OAuth2ProtectedResourceDetails resourceDetails() {
final AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setClientId(“#######”);
details.setClientSecret(“#######”);
details.setAccessTokenUri("https://tokenserver/as/token.oauth2");
details.setUserAuthorizationUri("https://authserver/as/authorization.oauth2");
details.setScope(Arrays.asList("openid"));
details.setGrantType("authorization_code");
details.setPreEstablishedRedirectUri("https://localhost:8443/login");
details.setUseCurrentUri(false);
return details;
}
@Bean
public OAuth2RestTemplate restTemplate(final OAuth2ClientContext clientContext) {
return new OAuth2RestTemplate(resourceDetails(), clientContext);
}
}
}
我正在为客户端使用以下软件包:
<!-- security -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
我的资源服务器配置如下:
@Configuration
@EnableResourceServer
@Profile({"dev"})
public class ResourceServerConfig extends
ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {// @formatter:off
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.antMatchers("/login**", "/##/token.oauth2", "/as/authorization.oauth2").permitAll()
// .antMatchers("/**").hasAuthority("ROLE_USER")
.and()
.logout()
.deleteCookies("remove")
.invalidateHttpSession(true)
.permitAll()
.and()
.csrf().disable();
}// @formatter:on
@Bean
public ResourceServerTokenServices tokenService() {
RemoteTokenServices tokenServices = new RemoteTokenServices();
tokenServices.setClientId(“####”);
tokenServices.setClientSecret(“#####”);
tokenServices.setCheckTokenEndpointUrl("https://tokenserver/##/token.oauth2");
return tokenServices;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenServices(this.tokenService());
}
}
我正在使用以下软件包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
我的客户端控制器尝试像这样访问此资源:
@RestController
@Profile({"dev"})
class MainController {
@Autowired
private OAuth2RestTemplate restTemplate;
@RequestMapping("/somepath")
public final String home() {
return "/";
}
@SuppressWarnings("unused")
@RequestMapping
public ModelAndView login() {
// OAuth2AccessToken accessToken = restTemplate.getAccessToken();
final HelloWorld helloWorld = restTemplate.getForObject("https://localhost:8444/openidconnect-resource-server/api/1", HelloWorld.class);
return new ModelAndView("landingPage");
}
}
不幸的是,我不断出现以下错误:
OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.connector.RequestFacade@7e4514ea
AntPathRequestMatcher : Request '/login' matched by universal pattern '/**'
security.web.FilterChainProxy : /login?code=#####&state=## at position 1 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
security.web.FilterChainProxy : /login?code=######&state=## at position 2 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
HttpSessionSecurityContextRepository : No HttpSession currently exists
HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
security.web.FilterChainProxy : /login?code=####&state=## at position 3 of 10 in additional filter chain; firing Filter: 'HeaderWriterFilter'
security.web.FilterChainProxy : /login?code=#####&state=## at position 4 of 10 in additional filter chain; firing Filter: 'CsrfFilter'
security.web.FilterChainProxy : /login?code=####&state=## at position 5 of 10 in additional filter chain; firing Filter: 'LogoutFilter'
matcher.AntPathRequestMatcher : Request 'GET /login' doesn't match 'POST /logout
security.web.FilterChainProxy : /login?code=XRuHsIOKxNEzUkljeWn7lVfZcxTisziI7ZsAAADJ&state=UV13ug at position 6 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
security.web.FilterChainProxy : /login?code=XRuHsIOKxNEzUkljeWn7lVfZcxTisziI7ZsAAADJ&state=UV13ug at position 7 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
security.web.FilterChainProxy : /login?code=XRuHsIOKxNEzUkljeWn7lVfZcxTisziI7ZsAAADJ&state=UV13ug at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
security.web.FilterChainProxy : /login?code=XRuHsIOKxNEzUkljeWn7lVfZcxTisziI7ZsAAADJ&state=UV13ug at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
security.web.FilterChainProxy : /login?code=XRuHsIOKxNEzUkljeWn7lVfZcxTisziI7ZsAAADJ&state=UV13ug at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
AntPathRequestMatcher : Request 'GET /login' doesn't match 'POST /logout
AntPathRequestMatcher : Checking match of request : '/login'; against '/actuator/health'
AntPathRequestMatcher : Checking match of request : '/login'; against '/login**'
FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /login?code=#####&state=##; Attributes: [permitAll]
audit.listener.AuditListener : AuditEvent [timestamp=2018-08-07T22:28:38.785Z, principal=, type=AUTHENTICATION_FAILURE, data={type=org.springframework.security.authentication.AuthenticationCredentialsNotFoundException, message=An Authentication object was not found in the SecurityContext}]
ExceptionTranslationFilter : Authentication exception occurred; redirecting to authentication entry point
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
答案 0 :(得分:0)
我的实现存在几个问题,主要的问题是OAuth2ProtectedResourceDetails扩展类中不包括userinfo端点。我将该配置移至application.properties。
我的客户端配置现在看起来像:
@Configuration
@EnableOAuth2Sso
@ComponentScan("com.myclient")
@Profile({"dev"})
public class OIDCClientConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {// @formatter:off
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/**").hasRole("USER")
.and()
.csrf().disable()
.logout()
.permitAll()
.deleteCookies("remove")
.clearAuthentication(true)
.invalidateHttpSession(true)
.logoutSuccessUrl("https://####/logout")
.and().httpBasic().disable();
}// @formatter:on
@Override
public void configure(WebSecurity web) throws Exception {// @formatter:off
web
.ignoring()
.mvcMatchers(
"/**/favicon.ico",
"/webjars/**");
}// @formatter:on
// thymeleaf
@Bean
public ClassLoaderTemplateResolver templateResolver() {
final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}
@Bean
public ThymeleafViewResolver viewResolver() {
final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
return viewResolver;
}
// end thymeleaf
}
我的MainController看起来像这样:
package myclient.controller;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Profile;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@RestController
class MainController {
@RequestMapping(value = "/home")
public ModelAndView landingPage() {
return new ModelAndView("landingPage");
}
}
我的application.properties看起来像这样:
# Allow Thymeleaf templates to be reloaded at dev time
spring.thymeleaf.cache=false
server.tomcat.accesslog.enabled=true
server.tomcat.basedir=target/tomcat
server.ssl.key-store-type=JKS
server.ssl.key-store=classpath:keystore
server.ssl.key-store-password=changeit
server.ssl.key-alias=tomcat
server.port=8443
#context path
server.servlet.context-path=/
spring.main.web-application-type=SERVLET
spring.main.banner-mode=off
spring.profiles.active=default,dev
# spring.profiles.active=dev
# SECURITY OAUTH2 CLIENT (OAuth2ClientProperties)
security.oauth2.client.client-id=####
security.oauth2.client.client-secret=#####
security.oauth2.client.authorized-grant-types=authorization_code
security.oauth2.client.access-token-uri=https://###/##/###
security.oauth2.client.user-authorization-uri=https://###/##/###
security.oauth2.client.scope=openid
security.oauth2.client.use-current-uri=true
security.oauth2.resource.user-info-uri=####
logging.level.org.springframework=DEBUG
是的,我从保护资源上退了一步,但走了一步:)