https://spring.io/guides/gs/securing-web/
创建不安全的Web应用程序
在将安全性应用于Web应用程序之前,您需要一个Web应用程序来保护安全。本节中的步骤将指导您创建一个非常简单的Web应用程序。然后在下一节中使用Spring Security保护它。
Web应用程序包括两个简单视图:主页和“Hello World”页面。主页在以下Thymeleaf模板中定义:
src/main/resources/templates/home.html
Spring Security Example
Welcome!
Click here to see a greeting.
如您所见,这个简单的视图包含指向页面“/ hello”的链接。这在以下Thymeleaf模板中定义:
src/main/resources/templates/hello.html
Hello World!
Hello world!
Web应用程序基于Spring MVC。因此,您需要配置Spring MVC并设置视图控制器以公开这些模板。这是在应用程序中配置Spring MVC的配置类。
src/main/java/hello/MvcConfig.java
package hello;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
}
该addViewControllers()方法(覆盖同名方法WebMvcConfigurer)添加了四个视图控制器。其中两个视图控制器引用名称为“home”(定义于home.html)的视图,另一个引用名为“hello”(定义于hello.html)的视图。第四个视图控制器引用另一个名为“login”的视图。您将在下一部分中创建该视图。
此时,您可以跳转到使应用程序可执行并运行应用程序而无需登录任何内容。
通过创建基本简单Web应用程序,您可以为其添加安全性。
假设您要阻止未经授权的用户在“/ hello”查看问候语页面。就像现在一样,如果用户单击主页上的链接,他们会看到问候语,没有障碍阻止他们。您需要添加一个屏障,强制用户在查看该页面之前登录。
您可以通过在应用程序中配置Spring Security来实现。如果Spring Security位于类路径上,则Spring Boot会自动使用“基本”身份验证来保护所有HTTP端点。但您可以进一步自定义安全设置。您需要做的第一件事是将Spring Security添加到类路径中。
使用Gradle,这将是dependencies闭包中的一行:
build.gradle
dependencies {
...
compile("org.springframework.boot:spring-boot-starter-security")
...
}
使用Maven,这将是一个额外的条目添加到:
pom.xml
...
org.springframework.boot
spring-boot-starter-security
...
这是一个安全配置,可确保只有经过身份验证的用户才能看到秘密问候语:
src/main/java/hello/WebSecurityConfig.java
package hello;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
本WebSecurityConfig类与注释@EnableWebSecurity,使Spring Security的网络安全支持,并提供了Spring MVC的整合。它还扩展WebSecurityConfigurerAdapter并覆盖了其几种方法,以设置Web安全配置的一些细节。
该configure(HttpSecurity)方法定义了哪些URL路径应该被保护,哪些不应该被保护。具体而言,“/”和“/ home”路径配置为不需要任何身份验证。必须对所有其他路径进行身份验证。
当用户成功登录时,它们将被重定向到先前请求的身份验证页面。有一个自定义的“/ login”页面loginPage(),每个人都可以查看它。
至于该userDetailsService()方法,它使用单个用户设置内存中用户存储。该用户被赋予用户名“user”,密码为“password”,角色为“USER”。
现在我们需要创建登录页面。“登录”视图已有一个视图控制器,因此您只需创建登录视图本身:
src/main/resources/templates/login.html
Spring Security Example
Invalid username and password.
You have been logged out.
如您所见,此Thymeleaf模板只显示一个表单,该表单捕获用户名和密码并将其发布到“/ login”。根据配置,Spring Security提供了一个拦截该请求并对用户进行身份验证的过滤器。如果用户无法进行身份验证,页面将重定向到“/ login?error”,我们的页面将显示相应的错误消息。成功注销后,我们的应用程序将发送到“/ login?logout”,我们的页面会显示相应的成功消息。
最后,我们需要为用户提供显示当前用户名和注销的方法。更新为hello.html当前用户打招呼并包含“注销”表单,如下所示
src/main/resources/templates/hello.html
Hello World!
Hello [[${#httpServletRequest.remoteUser}]]!
我们使用Spring Security的集成显示用户名HttpServletRequest#getRemoteUser()。“注销”表单将“POST”发送到“/ logout”。成功注销后,它会将用户重定向到“/ login?logout”。
使应用程序可执行
虽然可以将此服务打包为传统的Web应用程序存档或WAR文件以便部署到外部应用程序服务器,但下面演示的更简单的方法创建了一个独立的应用程序。您将所有内容打包在一个可执行的JAR文件中,由一个好的旧Java main()方法驱动。在此过程中,您使用Spring的支持将Tomcat servlet容器嵌入为HTTP运行时,而不是部署到外部实例。
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Throwable {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication 是一个便利注释,添加了以下所有内容:
@Configuration 标记该类作为应用程序上下文的bean定义的来源。
@EnableAutoConfiguration 告诉Spring Boot开始根据类路径设置,其他bean和各种属性设置添加bean。
通常你会添加@EnableWebMvc一个Spring MVC应用程序,但Spring Boot会在类路径上看到spring-webmvc时自动添加它。这会将应用程序标记为Web应用程序并激活关键行为,例如设置a DispatcherServlet。
@ComponentScan告诉Spring在包中寻找其他组件,配置和服务hello,允许它找到控制器。
该main()方法使用Spring Boot的SpringApplication.run()方法启动应用程序。您是否注意到没有一行XML?也没有web.xml文件。此Web应用程序是100%纯Java,您无需处理配置任何管道或基础结构。
您可以使用Gradle或Maven从命令行运行该应用程序。或者,您可以构建一个包含所有必需依赖项,类和资源的可执行JAR文件,并运行该文件。这使得在整个开发生命周期中,跨不同环境等将服务作为应用程序发布,版本和部署变得容易。
如果您使用的是Gradle,则可以使用./gradlew bootRun。或者您可以使用构建JAR文件./gradlew build。然后你可以运行JAR文件:
java -jar build / libs / gs-secured-web-0.1.0.jar
如果您使用的是Maven,则可以使用该应用程序运行该应用程序./mvnw spring-boot:run。或者您可以使用构建JAR文件./mvnw clean package。然后你可以运行JAR文件:
java -jar target / gs-secured-web-0.1.0.jar
上面的过程将创建一个可运行的JAR。您也可以选择构建经典WAR文件。
…应用程序启动…
应用程序启动后,将浏览器指向http:// localhost:8080。你应该看到主页:
当您单击该链接时,它会尝试将您带到问候页面/hello。但是因为该页面是安全的并且您还没有登录,它会将您带到登录页面:
如果你使用不安全的版本跳到这里,那么你将看不到这个登录页面。随意备份并编写其余基于安全性的代码。
在登录页面上,分别输入“user”和“password”作为用户名和密码字段,以测试用户身份登录。提交登录表单后,您将通过身份验证,然后转到问候语页面:
如果单击“注销”按钮,您的身份验证将被撤消,并返回到登录页面,并显示一条消息,指示您已注销。
恭喜!您已经开发了一个使用Spring Security保护的简单Web应用程序。