我的基本设置如下:
(公共网站)< ----> (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;
}
}