Spring Boot 和 Spring Cloud Security OAUTH 2 SSO 在最新版本中失败

Posted

技术标签:

【中文标题】Spring Boot 和 Spring Cloud Security OAUTH 2 SSO 在最新版本中失败【英文标题】:Spring Boot and Spring Cloud Security OAUTH 2 SSO Failing with latest releases 【发布时间】:2017-10-24 04:51:12 【问题描述】:

我正在尝试将示例 Spring Boot 和带有 OAuth 的 Spring Cloud Security 从 Spring Boot 1.4.1 + Brixton.RELEASE 升级到 Spring Boot 1.5.3+ Dalston.RELEASE。然而,这是一个漫长的努力,没有任何成功。

似乎由于某种原因,资源服务器安全过滤器链没有被触发。因此,默认安全过滤器链正在处理对“/me”或“/user”的调用。我在想这是否是订单问题。但试图显式设置安全过滤器链的顺序如下

身份验证服务器 6 网页默认 5 资源服务器 3(硬编码 ??)

由于默认过滤器链正在处理请求,它总是会转到登录页面,生成 html 并且 SSO 客户端(服务器端 thymeleaf Web UI)失败。

源码如下

授权服务器

@SpringBootApplication
public class MyAuthServerApplication 

public static void main(String[] args) 
    SpringApplication.run(MyAuthServerApplication.class, args);


然后是授权服务器配置

@Configuration
@EnableAuthorizationServer
@Order(6)
public class AuthorizationServerConfigurer extends A 
uthorizationServerConfigurerAdapter 


@Override
public void configure(ClientDetailsServiceConfigurer clients) throws 
Exception 
    clients.inMemory()
            .withClient("myauthserver")
            .secret("verysecretpassword")
            .redirectUris("http://localhost:8080/")
            .authorizedGrantTypes("authorization_code", "refresh_token")
            .scopes("myscope")
            .autoApprove(true);


然后是资源服务器类

@Configuration
@EnableResourceServer
public class ResourceServerConfigurer extends 
ResourceServerConfigurerAdapter 

@Override
public void configure(HttpSecurity http) throws Exception 
    http.antMatcher("/user")
            .authorizeRequests()
            .anyRequest()
            .authenticated();


Web MVC 配置

@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter 

 @Override
 public void addViewControllers(ViewControllerRegistry registry) 
    registry.addViewController("login").setViewName("login");
 
 

默认的spring安全配置

@Configuration
@EnableWebSecurity
@Order(9)
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter 


@Override
protected void configure(HttpSecurity http) throws Exception 
    http
            .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
            .and().csrf()
            .and().formLogin().loginPage("/login");


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception 

    auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER")
            .and()
                .withUser("admin").password("admin").roles("USER", "ADMIN");


资源控制器

@RestController
public class ResourceController 

@RequestMapping(value =  "/user" , produces = "application/json")
public Map<String, Object> user(OAuth2Authentication user) 
    Map<String, Object> userDetails = new HashMap<>();
    userDetails.put("user", user.getUserAuthentication().getPrincipal());
    userDetails.put("authorities",

AuthorityUtils.
 authorityListToSet(user.getUserAuthentication().getAuthorities()));
    return userDetails;

最后是配置 - 身份验证服务器的 application.yml

server:
  port: 9090
  contextPath: /auth

logging:
  level:
      org.springframework: INFO
      org.springframework.security: DEBUG

此处未显示 login.html Thymeleaf 模板。

OAUTH 2 SSO 客户端网络应用

@SpringBootApplication
public class MyWebsiteApplication 

public static void main(String[] args) 
    SpringApplication.run(MyWebsiteApplication.class, args);


网络安全配置

@Configuration
@EnableOAuth2Sso
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter 

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.authorizeRequests()
            .antMatchers("/").permitAll()   // Allow navigating to index 
 page,
            .anyRequest().authenticated();  // but secure all the other URLs


网络控制器

@控制器 公共类 MyWebsiteController

/**
 * Default index page to verify that our application works.
 */
@RequestMapping("/")
@ResponseBody
public String helloWorld() 
    return "Hello world!";


/**
 * Return a ModelAndView which will cause the 
'src/main/resources/templates/time.html' template to be rendered,
 * with the current time.
 */
@RequestMapping("/time")
public ModelAndView time() 
    ModelAndView mav = new ModelAndView("time");
    mav.addObject("currentTime", getCurrentTime());
    return mav;


private String getCurrentTime() 
    return LocalTime.now().format(DateTimeFormatter.ISO_LOCAL_TIME);


应用程序配置 - 客户端 Web 应用程序的 application.yml

server:
  port: 8080
  contextPath: /

security:
  oauth2:
  client:
    accessTokenUri: http://localhost:9090/auth/oauth/token
    userAuthorizationUri: http://localhost:9090/auth/oauth/authorize
    clientId: myauthserver
    clientSecret: verysecretpassword
  resource:
    userInfoUri: http://localhost:9090/auth/user

time.html 页面的 Thymeleaf 模板未在此处显示。

一定有一些微妙的小配置是错误的,或者是一些我不知道的错误。任何帮助或想法都非常感谢。

【问题讨论】:

【参考方案1】:

解决方案

猜对了,获得的安全过滤器链的顺序已更改。这是Spring 1.5.x release note

的链接

修改后的代码在这里,稍后会上传到 Github。身份验证服务器配置的所有更改。

Spring 安全配置 - 移除 @Order 注解。

@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter 


@Override
protected void configure(HttpSecurity http) throws Exception 
    http
            .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
            .and().csrf()
            .and().formLogin().loginPage("/login");


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception 

    auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER")
            .and()
                .withUser("admin").password("admin").roles("USER", "ADMIN");


然后修改application.yml如下

server:
  port: 9090
  contextPath: /auth

logging:
  level:
    org.springframework: INFO
    org.springframework.security: DEBUG

security:
  oauth2:
    resource:
    filter-order : 3

就是这样,然后在身份验证服务器上进行身份验证后,时间将显示在客户端应用程序 /time url 上。

【讨论】:

嘿!你有时间将代码添加到 github 吗?我真的很想研究它。因为我似乎也有同样的问题。

以上是关于Spring Boot 和 Spring Cloud Security OAUTH 2 SSO 在最新版本中失败的主要内容,如果未能解决你的问题,请参考以下文章

《02.Spring Boot连载:Spring Boot实战.Spring Boot核心原理剖析》

Spring Boot系列 Spring Boot介绍和基础POM文件

Spring Boot系列Spring Initializer快速创建Spring Boot项目

spring-boot-starter-web 和 spring-boot-starter-webflux 不能一起工作吗?

Spring Boot集成Spring Cache 和 Redis

Spring boot 和 Spring Actuator - 禁用安全性