使用spring-boot OAuth2服务器保护Spring启动应用程序

时间:2015-09-04 13:33:16

标签: angularjs spring-security spring-boot

我正在学习如何使用Spring-boot保护应用程序以及如何使用本教程设置OAuth2服务器:SSO with OAuth2: Angular JS and Spring Security Part V。如果我从referenced Github account获取来源,它可以工作,但不符合我的需要。

这是我理想的架构:

Architecture

1)由于nginx重定向,前端(带有角度和引导程序的纯html / js / css)和后端之间有明显的分离。 nginx在端口80上接收到每个请求。然后,如果它以/ api开头,则重定向到端口8080.否则,它将由nginx作为静态文件提供。

这是相应的nginx conf:

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /home/adenoyelle/IdeaProjects/myapp/frontend;
    index index.html index.htm;

    location /api {
            proxy_set_header Host $http_host;
            proxy_redirect off;
            proxy_pass http://127.0.0.1:8080;
    }
 }

此部分有效

2)启用登录表单,而不是使用“基本身份验证”对话框。如教程中所述,我创建了一个登录表单,然后我在Angular的一侧使用此选项来阻止出现“基本身份验证”对话框:

$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
  

自定义“X-Requested-With”是浏览器客户端发送的传统标头,它曾经是Angular中的默认标头,但是它们在1.3.0中取出了它。 Spring Security通过不在401响应中发送“WWW-Authenticate”标头来响应它,因此浏览器不会弹出身份验证对话框(这在我们的应用程序中是可取的,因为我们想要控制身份验证)。

无法正常工作,即每当我尝试访问受保护资源或提交登录表单时,都会显示“基本身份验证”弹出窗口!

在Chrome控制台中,我可以看到请求标头中的X-Requested-With:XMLHttpRequest和401响应中的WWW-Authenticate:Basic realm="Spring"标头。

以下是后端的相应代码:

@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
public class Backend {

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

  @Configuration
  protected static class SecurityConfiguration extends OAuth2SsoConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
      http.logout().and()
          .authorizeRequests()
          .antMatchers("/login").permitAll()
          .anyRequest().authenticated().and().csrf()
          .csrfTokenRepository(csrfTokenRepository()).and()
          .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
    }

    private Filter csrfHeaderFilter() {
      return new OncePerRequestFilter() {
        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
          CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
              .getName());
          if (csrf != null) {
            Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
            String token = csrf.getToken();
            if (cookie == null || token != null
                && !token.equals(cookie.getValue())) {
              cookie = new Cookie("XSRF-TOKEN", token);
              cookie.setPath("/");
              response.addCookie(cookie);
            }
          }
          filterChain.doFilter(request, response);
        }
      };
    }

    private CsrfTokenRepository csrfTokenRepository() {
      HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
      repository.setHeaderName("X-XSRF-TOKEN");
      return repository;
    }
  }

}

3)我希望后端接收登录请求,感谢zuul,我希望它能转发到授权服务器,但也许我误解了这一部分。

实际发生的事情:当我尝试提交登录表单时,我看到基本身份验证弹出窗口,我关闭它然后我可以在后端服务器上看到跟踪:

  

15:21:13.664 [http-nio-8080-exec-6] INFO osbaaudit.listener.AuditListener - AuditEvent [timestamp = Fri Sep 04 15:21:13 CEST 2015,principal = user,type = AUTHENTICATION_FAILURE, data = {type = org.springframework.security.authentication.BadCredentialsException,message = Bad credentials}]

并且授权服务器上没有任何痕迹!

以下是后端配置的相关部分:

spring.oauth2.client.access-token-uri=http://localhost:9999/uaa/oauth/token
spring.oauth2.client.user-authorization-uri=http://localhost:9999/uaa/oauth/authorize
spring.oauth2.client.client-id=acme
spring.oauth2.client.client-secret=acmesecret

zuul.routes.user.path=/user/**
zuul.routes.user.url=http://localhost:9999/uaa/user

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

禁用基本身份验证

@Override
public void configure(HttpSecurity http) throws Exception {
  http.logout()
      .and()
      .httpBasic().disable()
      .and()
      .authorizeRequests()
      .antMatchers("/login").permitAll()
      .anyRequest().authenticated().and().csrf()
      .csrfTokenRepository(csrfTokenRepository()).and()
      .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}

答案 1 :(得分:0)

我不确定您的问题是否已得到解决。

由于项目Javascript文件的弹簧授权,您正在获取浏览器弹出窗口。如果你查看教程第7部分,则提到默认情况下js / **文件夹中的内容是不安全的。

  

注意:所有客户端代码都在一个目录下,“js”(index.html除外,因为它是一个“欢迎”页面,并从“静态”目录自动加载)。这是故意的,因为它可以轻松地将单个Spring Security访问规则应用于所有静态资源。这些都是不安全的(因为/ js / **在Spring Boot应用程序中默认是不安全的),但是你可能需要其他应用程序的其他规则,在这种情况下你会选择不同的路径。

如果将文件放在js / **文件夹下,则不会显示浏览器弹出窗口。另一种方法是在http configure方法下在antmatchers中提到你的文件夹。

我希望这能解决问题。

感谢。