github的项目源码,建议 导入项目后,运行 然后看着博客学习。
document\urp.sql 数据库 sql
能力提升
博客只是能把你领进门,有很多特性我没有讲,感兴趣的 可以看 官方 文档
spring sercurity官方文档
如果只是满足于怎么样spring sercurity博客就可以,如果想各种定制那么还是官方文档和源码吧。
在上一篇博客登录用户,我们需要对资源 url进行保护,这个就用到了鉴权。
我个人理解,spring sercurity 的鉴权的类 主要有这两个类。当然 我们也可以自定义类来完成相同的功能。
- FilterSecurityInterceptor 这个类和我们配置文件的authorizeRequests息息相关,例如 那个url 需要登录,哪个url 不需要登录 就可以访问。
- MethodSecurityInterceptor方法层面的权限控制,和注解一起使用的,例如@PreAuthorize
这两个一个是处理 认证的,也就是 你登录了没有,一个是 你看你这个用户 有没有权限能用这个。 这时候 也需要 有人会问,如果没登录 就到MethodSecurityInterceptor 会怎么样?
这里我很明确的回答一下。如果 一个url你permitAll了,在controller方法哪里 又使用了注解@PreAuthorize。那么你访问这个url 还是提示没有权限的。 因为permitAll()会默认的生成一个匿名用户,@PreAuthorize进行权限鉴权时候,是对匿名用户鉴权的。
AbstractSecurityInterceptor是FilterSecurityInterceptor 和MethodSecurityInterceptor的共同父类。重写他的beforeInvocation方法就可以实现 自定义的权限鉴权业务
鉴权流程
1. 查找与当前请求关联的“configuration attributes”
2. 提交 secure object(安全对象),Authentication ,configuration attributes,给AccessDecisionManager 的decide方法 进行认证。在FilterSecurityInterceptor中,decide的参数object类型为FilterInvocation,MethodSecurityInterceptor中object类型为MethodInvocation,具体类型是ReflectiveMethodInvocation
3. 可选的 ,在发生调用的 改变 Authentication
4. 假设已授予访问权限,允许继续对安全对象调用,就是可以访问这个安全对象
5. 如果配置了 AfterInvocationManager 就调用它, 如果 上面出现异常 就不会调用它。
流程 进入SecurityInterceptor后,首先走 它的doFilter方法,包装一下request ,response。→调用invoke() →调用beforeInvocation方法→调用SecurityMetadataSource获取ConfigAttribute集合→丛SecurityContext里面取出Authentication认证对象,如果取出的Authentication没有认证过,那就调用authenticationManager再认证一下→调用accessDecisionManager的decide方法 进行权限鉴权。抛异常的就是不允许访问,没有异常的 就是通过的。→调用RunAsManager为当前的current secure object创建一个临时的对象。→beforeInvocation返回一个InterceptorStatusToken→尝试再调用FilterChain进行过滤→调用finallyInvocation设置SecurityContext→最后调用afterInvocation,如果有afterInvocationManager 则再进行一次鉴权过称。结束
FilterSecurityInterceptor
没有什么好讲的。反正 只要知道流程了,这个类我们不能替换调用,只能替换掉这个类的内部引用。或者 在Filter Chain 哪里 加入 我们自定义的类。也就是 自定义的类和FilterSecurityInterceptor 共存。如下如所示
我们可以在Filter Chain 添加自定义的类 FilterSecurityInterceptor 也一直会存在 。
在配置文件里面 配置如下
package com.example.sercurity.config;
import com.example.sercurity.component.MyFilter;
import com.example.sercurity.component.RestAuthenticationEntryPoint;
import com.example.sercurity.component.RestfulAccessDeniedHandler;
import com.example.sercurity.config.sercurity.*;
import com.example.sercurity.service.PermissonService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
/**
* 配置token登录的
*
* @Author: plani
* 创建时间: 2019/8/16 17:50
*/
@Configuration
@EnableWebSecurity
//启用 方法鉴权
//下面这个注解 ,项目只能有一个类可以使用,要注意
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
@Order(3)
public class TokenSecurityConfig extends WebSecurityConfigurerAdapter {
private Logger logger = LoggerFactory.getLogger(FormSecurityConfig.class);
@Autowired
private PermissonService permissonService;
@Autowired
private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
private MyAuthticationProvider myAuthticationProvider;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()//跨域攻击去除
.sessionManagement()