- SpringSecurity介绍
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
SpringSecurity官网: https://spring.io/projects/spring-security
SpringSecurity的种认证模式:
1) HttpBasic模式
2) FormLogin模式
- HttpBasic模式
- 创建boot项目
结构如下:
在pom.xml添加依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
- 创建订单Controller
配置对应查询、修改等按钮和页面,这里主要是用于演示效果。import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class OrderController { // 首页 @RequestMapping("/") public String index() { return "index"; } // 查询订单 @RequestMapping("/showOrder") public String showOrder() { return "showOrder"; } // 添加订单 @RequestMapping("/addOrder") public String addOrder() { return "addOrder"; } // 修改订单 @RequestMapping("/updateOrder") public String updateOrder() { return "updateOrder"; } // 删除订单 @RequestMapping("/deleteOrder") public String deleteOrder() { return "deleteOrder"; } // 自定义登陆页面 @GetMapping("/login") public String login() { return "login"; } }
- 添加security配置类
import org.springframework.context.annotation.Bean; 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.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.stereotype.Component; /** * SpringSecurity配置 * @author xiaobo * @Description SecurityConfig * @createTime 2020-06-10 7:14 */ @Component @EnableWebSecurity // 开启security public class SecurityConfig extends WebSecurityConfigurerAdapter { // 用户认证信息 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 设置用户账号信息和权限 auth.inMemoryAuthentication().withUser("admin").password("123456").authorities("addOrder"); } // 配置HttpSecurity拦截URL protected void configure(HttpSecurity http) throws Exception { // 拦截所有请求并选择httpBasic模式 http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic(); } @Bean public static NoOpPasswordEncoder passwordEncoder() { return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); } }
- 启动
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Hello world! * */ @SpringBootApplication public class AppSpringSecurity { public static void main( String[] args ) { SpringApplication.run(AppSpringSecurity.class); } }
- 测试
访问: http://127.0.0.1:8080/
账号/密码: admin/123456
- FormLogin模式
- 修改SecurityConfig类
// 配置HttpSecurity拦截URL protected void configure(HttpSecurity http) throws Exception { // 拦截所有请求并选择formLogin模式 http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().formLogin(); }
- 测试......
-
用户自定义页面和权限
- 实现不同用户的权限控制
在在SecurityConfig.java配置import org.springframework.context.annotation.Bean; 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.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.stereotype.Component; /** * SpringSecurity配置 * @author xiaobo * @Description SecurityConfig * @createTime 2020-06-10 7:14 */ @Component @EnableWebSecurity // 开启security public class SecurityConfig extends WebSecurityConfigurerAdapter { // 用户认证信息 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 设置用户账号信息和权限 // 配置admin用户拥有查看、添加、更新、删除订单权限 auth.inMemoryAuthentication().withUser("admin").password("123456").authorities("showFlag", "addFlag", "updateFlag","deleteFlag"); // 配置ben用户拥有查看、添加订单权限 auth.inMemoryAuthentication().withUser("ben").password("123456").authorities("showFlag", "addFlag"); } // 配置HttpSecurity拦截URL protected void configure(HttpSecurity http) throws Exception { // 拦截所有请求并选择httpBasic模式 /showOrder:url地址 showFlag:每个url对应的标识,用户绑定标识 http.authorizeRequests(). antMatchers("/showOrder").hasAnyAuthority("showFlag"). antMatchers("/addOrder").hasAnyAuthority("addFlag"). antMatchers("/updateOrder").hasAnyAuthority("updateFlag"). antMatchers("/deleteOrder").hasAnyAuthority("deleteFlag"). antMatchers("/**").fullyAuthenticated().and().formLogin(); } @Bean public static NoOpPasswordEncoder passwordEncoder() { return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); } }
- 实现自定义权限不足页面
// 配置类
// 自定义403的controllerimport org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; @Configuration public class WebServerAutoConfiguration { @Bean public ConfigurableServletWebServerFactory webServerFactory() { TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400"); ErrorPage errorPage401 = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401"); ErrorPage errorPage403 = new ErrorPage(HttpStatus.FORBIDDEN, "/error/403"); ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"); ErrorPage errorPage415 = new ErrorPage(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "/error/415"); ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500"); factory.addErrorPages(errorPage400, errorPage401, errorPage403, errorPage404, errorPage415, errorPage500); return factory; } }
// 效果import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class ErrorController { @RequestMapping("/error/403") public String error() { return "/error/403"; } }
- 实现自定义登录页面
// 自定义登录的url和页面// 页面 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>登录页面</title> </head> <body> <h1>自定义登录页面</h1> <form action="/login" method="post"> <span>用户名称</span><input type="text" name="username" /> <br> <span>用户密码</span><input type="password" name="password" /> <br> <input type="submit" value="登陆"> </form> <#if RequestParameters['error']??> 用户名称或者密码错误 </#if> </body> </html>
// 在SecurityConfig.java配置登录页面// controller @GetMapping("/login") public String login() { return "login"; }
// 配置HttpSecurity拦截URL protected void configure(HttpSecurity http) throws Exception { // 拦截所有请求并选择httpBasic模式 /showOrder:url地址 showFlag:url地址的标识,可自定义须臾上面authorities一致 http.authorizeRequests(). antMatchers("/showOrder").hasAnyAuthority("showFlag"). antMatchers("/addOrder").hasAnyAuthority("addFlag"). antMatchers("/updateOrder").hasAnyAuthority("updateFlag"). antMatchers("/deleteOrder").hasAnyAuthority("deleteFlag"). antMatchers("/login").permitAll(). antMatchers("/**").fullyAuthenticated().and().formLogin().loginPage("/login").and().csrf().disable(); }
antMatchers("/login").permitAll()表示不拦截login的地址
// 测试:.loginPage("/login").and().csrf().disable(); 表示自定义登录页面,并禁止csrf
- 获取登录成功和失败的信息
创建登录成功和失败的handlerimport java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; // 认证成功 @Component public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse res, Authentication arg2) throws IOException, ServletException { System.out.println("用户认证成功"); res.sendRedirect("/"); } } import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; //认证失败 @Component public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse res, AuthenticationException auth) throws IOException, ServletException { System.out.println("登陆失败!"); res.sendRedirect("http://baidu.com"); } }
在SecurityConfig.java配置成功和失败的handler引入 @Autowired private MyAuthenticationSuccessHandler successHandler; @Autowired private MyAuthenticationFailureHandler failHandler; // 配置HttpSecurity拦截URL protected void configure(HttpSecurity http) throws Exception { // 拦截所有请求并选择httpBasic模式 /showOrder:url地址 showFlag:url地址的标识,可自定义须臾上面authorities一致 http.authorizeRequests(). antMatchers("/showOrder").hasAnyAuthority("showFlag"). antMatchers("/addOrder").hasAnyAuthority("addFlag"). antMatchers("/updateOrder").hasAnyAuthority("updateFlag"). antMatchers("/deleteOrder").hasAnyAuthority("deleteFlag"). antMatchers("/login").permitAll(). antMatchers("/**").fullyAuthenticated().and().formLogin().loginPage("/login") .successHandler(successHandler).failureHandler(failHandler).and().csrf().disable(); }