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模式
org.springframework.boot
spring-boot-starter-security
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";
}
}
配置对应查询、修改等按钮和页面,这里主要是用于演示效果。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);
}
}
// 配置HttpSecurity拦截URL
protected void configure(HttpSecurity http) throws Exception {
// 拦截所有请求并选择formLogin模式
http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().formLogin();
}
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();
}
}
import 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;
}
}
// 自定义403的controller 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";
}
}
// 效果// 页面
登录页面
自定义登录页面
<#if RequestParameters['error']??>
用户名称或者密码错误
#if>
// controller
@GetMapping("/login")
public String login() {
return "login";
}
// 在SecurityConfig.java配置登录页面 // 配置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
// 测试: import 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");
}
}
引入
@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();
}