SpringBoot学习笔记(2):用Spring Security来保护你的应用
快速开始
本指南将引导您完成使用受Spring Security保护的资源创建简单Web应用程序的过程。
参考资料:
SpringSecurity中文参考文档:点击进入
IBM参考文档:点击进入
使用Maven进行构建
首先,设置一个基本的构建脚本。在使用Spring构建应用程序时,您可以使用任何您喜欢的构建系统,但此处包含了使用Maven所需的代码。如果您不熟悉Maven,请参阅使用Maven构建Java项目。
<!--添加Security依赖--> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
创建一个不安全的应用
在将安全性应用于Web应用程序之前,您需要一个Web应用程序来保护安全。本节中的步骤将引导您创建一个非常简单的Web应用程序。然后在下一节中使用Spring Security保护它。
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"> <head> <title>Spring Security Example</title> </head> <body> <h1>Welcome!</h1> <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p> </body> </html>
如您所见,这个简单的视图包含指向页面“/ hello”的链接。这在以下Thymeleaf模板中定义:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"> <head> <title>Hello World!</title> </head> <body> <h1>Hello world!</h1> </body> </html>
Web应用程序基于Spring MVC。因此,您需要配置Spring MVC并设置视图控制器以公开这些模板。这是在应用程序中配置Spring MVC的配置类。
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 { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/home").setViewName("home"); registry.addViewController("/").setViewName("home"); registry.addViewController("/hello").setViewName("hello"); registry.addViewController("/login").setViewName("login"); } }
设置Spring Security
假设您要阻止未经授权的用户在“/ hello”查看问候语页面。就像现在一样,如果用户单击主页上的链接,他们会看到问候语,没有障碍阻止他们。您需要添加一个屏障,强制用户在查看该页面之前登录。
您可以通过在应用程序中配置Spring Security来实现。如果Spring Security位于类路径上,则Spring Boot会自动使用“基本”身份验证来保护所有HTTP端点。但您可以进一步自定义安全设置。您需要做的第一件事是将Spring Security添加到类路径中。
我们已经在Maven构建部分加入了相应配置,此处不再赘余。
这是一个安全配置,可确保只有经过身份验证的用户才能看到秘密问候语:
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() .permitAll() .and() .logout() .permitAll(); } @Bean public UserDetailsService userDetailsService() { UserDetails user = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build(); return new InMemoryUserDetailsManager(user); } }
WebSecurityConfig类使用@EnableWebSecurity进行批注,以启用Spring Security的Web安全支持并提供Spring MVC集成。它还扩展了WebSecurityConfigurerAdapter并覆盖了其几个方法来设置Web安全配置的一些细节。
configure(HttpSecurity)方法定义应该保护哪些URL路径,哪些不应该保护。具体而言,“/”和“/ home”路径配置为不需要任何身份验证。必须对所有其他路径进行身份验证。
当用户成功登录时,它们将被重定向到先前请求的身份验证页面。 loginPage()指定了一个自定义的“/ login”页面,允许每个人查看它。
对于userDetailsService()方法,它使用单个用户设置内存用户存储。该用户被赋予用户名“user”,密码为“password”,角色为“USER”。
效果演示
编写简单的安全性配置
启用Web安全性功能最简单配置
@Configuration @EnableWebSecurity //注解开启Spring Security的功能 public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ }
说明:
@EnableWebSecurity 将会启用Web安全功能,但他本身没有什么用。
我们还需要配置一个实现了WebSecurityConfigurer的Bean。
指定Web安全的细节
如果我们希望指定Web安全的细节,需要重载WebSecurityConfigureAdapter中的configure方法:
默认的configure Filter链:
protected void configure(HttpSecurity http) throws Exception { this.logger.debug("Using default configure(HttpSecurity).
If subclassed this will potentially override subclass configure(HttpSecurity)."); ((HttpSecurity)((HttpSecurity)((AuthorizedUrl)http.
authorizeRequests().
anyRequest()).
authenticated().
and()).
formLogin().
and()).
httpBasic(); }
基于内存的用户存储
protected void configure(AuthenticationManagerBuilder auth) throws Exception { //AuthenticationManagerBuilder提供了有多个方法来配置Security对认证的支持。 auth.inMemoryAuthentication() //启用内存用户存储 .withUser("user").password("password").roles("USER").and() .withUser("admin").password("password").roles("USER","ADMIN"); }
基于数据库表进行认证
protected void configure(AuthenticationManagerBuilder auth) throws Exception { //AuthenticationManagerBuilder提供了有多个方法来配置Security对认证的支持。 auth.jdbcAuthentication() .dataSource(dataSource) .usersByUsernameQuery("SELECT username,password,enable FROM mybatis.user WHERE username=?") .authoritiesByUsernameQuery("SELECT username,role FROM mybatis.user WHERE username=?"); }
细粒度控制访问
protected void configure(HttpSecurity http) throws Exception { http .formLogin() //重写configure 需要添加formLogin来显示默认的登陆页面 .loginPage("/login")//登录页面的访问路径 .loginProcessingUrl("/check")//登录页面下表单提交的路径 .failureUrl("/login")//登录失败后跳转的路径 .defaultSuccessUrl("/show")//登录成功后默认跳转的路径 .and() .authorizeRequests() .antMatchers("/index.do").authenticated() .anyRequest().permitAll(); //其他请求是允许的,不需要经过认证和权限 }
基于注解的方式控制访问
简要介绍两种注解方式:
- @Secured()注解
- SpringBoot:
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true) //开启基于注解的安全验证
- SpringBoot:
- 基于表达式语法
- Spring Security中定义了四个支持使用表达式的注解,分别是@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter。其中前两者可以用来在方法调用前或者调用后进行权限检查,后两者可以用来对集合类型的参数或者返回值进行过滤。
public class HtmlController { @PreAuthorize("hasAuthority('ROLE_ADMIN')") @RequestMapping(value = "security.do") public String PreAuthorize() { return "@PreAuthorize:该注解用来确定一个方法是否应该被执行。" + "该注解后面跟着的是一个表达式,如果表达式的值为真,则该方法会被执行。" + "如 @PreAuthorize("hasRole('ROLE_USER')")" + "就说明只有当前用户具有角色 ROLE_USER的时候才会执行。"; } @Secured("ROLE_ADMIN") @RequestMapping(value = "security1.do") public String Security() { return "@Secured是由Spring Security定义的用来支持方法权限控制的注解。" + "它的使用也是需要启用对应的支持才会生效的。" + "通过设置global-method-security元素的secured-annotations=”enabled”" + "可以启用Spring Security对使用@Secured注解标注的方法进行权限控制的支持,其值默认为disabled。"; } }
配置自定义的用户服务
你好