在内存弹簧安全背后的反向代理(使用HTTPS)

时间:2017-09-22 08:36:40

标签: java security nginx spring-security reverse-proxy

我的基本设置如下:

(公共网站)< ----> (nginx端口80/443)< ----> (tomcat8端口8080 [使用/ admin和/ public的控制器类])

nginx在两个域名上运行,并充当单个tomcat8 servlet和公共Web之间的反向代理。

我选择此设置的原因是,我可以拥有一个面向公众的站点(http://example.com:80)和管理页面(https://admin.example.com:443)使用的servlet。代理将80转发到localhost:8080 / public,端口443转发到localhost:8080 / admin。

主要问题

与Spring Security相关的许多在线资源都是为了更简单的设置,您可以始终依赖于servlet中显示的URI与公共网站上显示的URI相同。

通常情况下,不必为/ on登录POST编写控制器,但在我的情况下,当我省略这样的方法时,在/ admin的控制器类中,我收到以下错误:状态“405 - 请求方法'POST'不受支持“。

另一方面,如果我在/ admin控制器类中包含POST on / login的控制器功能,则登录表单中的POST流量只是定向到该控制器;到目前为止,我找不到任何关于如何处理用户和密码的params的文档,因为通常Spring Security只是自动处理POST,因为它似乎是我使用Spring Security检查的Github repos,而不是实现任何@Controllers用于登录POST数据。

配置:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/admin/login", "/public/**").permitAll()
        .anyRequest().authenticated()
        .and().formLogin()
        .loginPage("/login").usernameParameter("email").passwordParameter("pass");
}

@Autowired
public void configureGlobal( AuthenticationManagerBuilder auth ) throws Exception {
    auth
        .inMemoryAuthentication()
        .withUser("john.smith@example.com").password("password").roles("USER");
}
}

控制器:

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;

@Controller
@RequestMapping(value = "/admin")
public class AdminController extends AbstractController {
    @RequestMapping(value = "")
    public String adminHome(
        ModelMap model
    ) {
        return "success";
    }
    @RequestMapping(value = "login", method = RequestMethod.GET)
    public String adminLogin(
        ModelMap model,
    ) throws IOException {
        getAdminConstants(model);
        return "admin/login";
    }
//  @RequestMapping(value = "login", method = RequestMethod.POST)
//  public String adminProcessLogin(
//      ModelMap model,
//  ) throws IOException {
//      return "success";
//  }
}

的web.xml:

[...]
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
[...]

安全配置文件中负责查看可以的部分,而无需用户登录就能完全按预期工作,例如当我访问example.com时(内部转发到localhost:8080 / public / $ uri),我没有被提示登录。当我进入管理页面(通过https://admin.example.com)时,我被正确提示登录。 然而,看来这些登录详细信息在此之后无处可去(尽管HTML表单确实提交了包含所搜索属性的POST请求)。我收到一个关于POST没有控制器的错误,或者如果我写了一个,那么我觉得Spring Security的整个目的都被抛到了窗外。

任何人都有类似设置的经验,他们会看到我缺少的东西吗?

编辑:添加相关的nginx配置:

server {
    listen 80;
    listen [::]:80;
    server_name admin.example.com;
    return 301 https://admin.example.com$request_uri;
}
server {
    listen 80;
    listen [::]:80;
    server_name example.com
    location / {
        proxy_pass http://127.0.0.1:8080/public/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name admin.example.com;
    ssl_certificate /etc/letsencrypt/live/admin.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/admin.example.com/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    location / {
        proxy_pass http://127.0.0.1:8080/admin/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

0 个答案:

没有答案