1. spring security概念
pring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作
2. 权限控制术语概念
认证:系统对访问的身份进行验证,确定身份是否能够访问系统,可以类比于现实生活中的小区管理,只有属于该小区的业主才能进入小区,认证就相当于是一个大门,只有认证通过的身份才能访问系统。
权限:验证身份是否能够访问资源,即拥有访问资源的权限,可以类比于生活中的小区管理,只有属于该小区的业主才能进入小区,但是进入小区后是否能进入某个单元,可以认为是否有进入某个单元的权限
3. spring security应用场景
Spring Security 正是 Spring 家族中的成员,Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案,广泛应用于后台管理框架中权限管理(认证和授权)
4. 需求描述
现在用一个简单的系统,里面有订单的新增、删除、修改、查看功能,现在想对访问系统的身份进行认证和授权管理,实现若果是admin账号登录,怎可以访问订单管理的所有功能;如果是userAdd账号登录,则只能访问新增和查看订单功能
5. 如何使用spring security实现权限控制(需求)
5.1依赖引入
在maven的pom文件中引入spring security依赖(一旦引入了依赖,即对系统添加了需要认证的功能,即访问系统需要进行登录)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
5.2添加spring security 配置类
配置的的作用有三:
作用一:通过注解开启过滤器链过滤功能(@EnableWebSecurity)
作用二:添加认证的用户和权限,重写com.yf.config.SecurityConfig#configure(org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder)方法
作用单:配置拦截资源的规则,重写com.yf.config.SecurityConfig#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)方法
package com.yf.config;
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;
/**
* @projectName: springboot-security
* @package: com.yf.config
* @className: SecurityConfig
* @author: yangfeng
* @description: spring-security配置类
* @date: 2022/11/23 15:26
* @version: 1.0
*/
//将该配置类交给spring容器管理
@Component
//开启过滤器链对请求的拦截
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* @Author yangfeng
* @Description //配置认证用户信息
* //配置认证用户的权限
* @Date 15:46 2022/11/23
* @param auth:
* @return void
* authentication 认证:检查并确认身份,确定身份是否能通过系统的第一道大门
**/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("123456").authorities("addOrder","showOrder","updateOrder","deleteOrder");
auth.inMemoryAuthentication().withUser("userAdd").password("123456").authorities("showOrder","addOrder");
}
/**
* @Author yangfeng
* @Description //配置拦截请求资源
* @Date 15:46 2022/11/23
* @param http:
* @return void
* authorize:批准、许可、授权的意思,检查并确定身份是否有访问特定资源的权限
**/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/showOrder").hasAnyAuthority("showOrder")
.antMatchers("/addOrder").hasAnyAuthority("addOrder")
.antMatchers("/updateOrder").hasAnyAuthority("updateOrder")
.antMatchers("/deleteOrder").hasAnyAuthority("deleteOrder")
.antMatchers("/**").fullyAuthenticated().and().formLogin();
}
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}
5.2.1认证方法核心剖析
5.2.2授权方法核心剖析
6.权限不足(403)时跳转到自定义的页面
在项目中添加服务器参数配置信息类,定义不同情况的请求路径
package com.yf.config;
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;
/**
* @Author yangfeng
* @Description // Web 服务器参数配置,可以配置默认错误页面
* @Date 14:42 2022/11/24
**/
@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;
}
}
在ErrorController中定义403转发的页面路径
package com.yf.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ErrorController {
// 403权限不足页面
@RequestMapping("/error/403")
public String error() {
System.out.println("403异常处理");
return "/error/403";
}
}
这样在用户权限不足的情况下就会跳转到/error/403页面
7.替换框架内置的登录页面为自定义登录页面
在com.yf.config.SecurityConfig配置类中的资源拦截方法中指定登录页面的路径
在对应的Controller中定义/login路径最终转发的页面地址
com.yf.controller.OrderController#login,在本节代码实例中,我们是在OrderController中定义login转发的路径定义到最终登录的页面
// 自定义登陆页面
@GetMapping("/login")
public String login() {
return "login";
}
8.登录成功和登录失败的判断
在项目中定义登录成功的handler处理类,实现AuthenticationSuccessHandler接口,处理登录成功后处理的逻辑
package com.yf.handler;
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("/");
}
}
同理定义登录失败handler处理类,实现AuthenticationFailureHandler接口,在登录失败的方法中添加自己的处理逻辑
package com.yf.handler;
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("https://www.baidu.com");
}
}
在配置类的资源拦截方法中加入注入登录成功和登录失败的handler
在资源拦截方法中添加对应的handler
完整代码参考请移步链接: github代码库