Spring sercrity
spring security 的学习过程
创建人:李浩杰
创建时间:2022/12/23
更新时间;2022/12/23
版本:0.0.1
环境介绍:
jdk:1.8
idea:2022.3
maven:3.86
springBoot:2.4.5
mysql: 5.8
案例:
使用瑞吉外卖,为其搭建Spring securty 框架。源码传送门
入门
引入坐标即可
<!-- spring security 坐标-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
引入坐标后访问资源将会跳转到spring security 自带的一个登录页面,进行登录 默认用户名:username 密码:在控制台打印
认证
一、自定义登录页面
基于入门案例,我们已经简单应用spring security 框架,但是表单提交的页面是框架生成的。那么我们该如何换成自己的登录页面呢?
1、创建spring security 配置类
/**
* spring security 配置类
*
* @author lihaojie
* @date 2022/12/22 16:59
**/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 身份安全管理器
*
* @param auth
* @return void
* @author lihaojie
* @date 2022/12/23 20:22
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
/**
* 登录认证采用basic认证:通过弹出对话框的形式提示输入密码,并将账户密码以basic64的形式加密传输
* 因为这种加密方式可以破解不安全,所以更多使用表单认证(默认)。
*/
/* http.httpBasic()
//所有请求都需要经过认证才能通过
.and().authorizeRequests().anyRequest().authenticated();*/
//开启表单
http .formLogin()
.loginPage("/backend/login.html") //自定义登录页面
.loginProcessingUrl("/login") //自定义登录页面所提交的路径
.defaultSuccessUrl("/backend/index.html",true) //登录成功后跳转到的页面,true:不管之前的访问地址都跳转到这里
.passwordParameter("password")
.usernameParameter("username")
.and()
.authorizeRequests().antMatchers("/backend/login.html").permitAll() //放行登录页面
.anyRequest().authenticated();
http.csrf().disable();
http.headers().frameOptions().disable();
}
}
二、基于数据库认证
到目前为止,我们一直在使用spring security 默认的username与password。但是我们想基于数据库中的username与password做认证。
1、实现MyUserDetailsServiceService
MyUserDetailsServiceService继承了UserDetailsServiceService,并重写loadUserByUsername方法。此方法内完成从数据库获根据username获取账户信息以及权限等信息,并将其封装为UserDetails并返回。如何封装呢?首先new 一个org.springframework.security.core.userdetails.User并将其赋值给UserDetails。返回的UserDetails被框架接受并自己将数据库的用户密码与前台传入的做对比。
/**
* 使用数据库账号登录
*
* @author lihaojie
* @date 2022/12/23 14:42
**/
@Service
public class MyUserDetailsServiceService implements UserDetailsService {
@Autowired
private EmployeeService employeeService;
/**
* 设置为从数据库获取账户与密码
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//1.通过employeeService查看数据库是否有吃用户名的员工
Employee employeeDb=employeeService.findByUsername(username);
//如果没有则抛出异常
if(employeeDb==null){
throw new UsernameNotFoundException("用户没找到:"+username);
}
//2、创建UserDetails并返回
//参数3: 权限集合
Collection<? extends GrantedAuthority> authorities =new ArrayList<>();
UserDetails userDetails = new org.springframework.security.core.userdetails.User
(username,
"{noop}"+ employeeDb.getPassword(), //{noop} :意思是密码不加密,使用明文
true, //enabled : 用户是否启用
true, //accountNonExpired : 用户是否过期
true, //credentialsNonExpired : 用户凭证是否过期
true, //accountNonLocked: 用户是否被锁定
authorities //权限集合,这里使用空集合
);
return userDetails;
}
}
2、SecurityConfig配置
需要两个步骤,
第一步: 通过注解注入MyUserDetailsServiceService
第二步:在身份管理器配置方法里面将userDetailsService换成我们自己写MyUserDetailsServiceService
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserDetailsServiceService myUserDetailsServiceService;
/**
* 身份安全管理器
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
auth.userDetailsService(myUserDetailsServiceService);
}
}
三、密码加密认证
在”基于数据库完成用户认证”中我们所使用的密码都是明文的,规则是通过对密码添加 ’{noop}‘前缀。那么下面将对spring security 中的密码编码进行一下研究。
Spring Security 中 PasswordEncoder 就是我们对密码进行编码的工具接口。此接口只有两个功能:1. 匹配验证 2. 密码编码
我们可以看到PasswordEncorder接口有众多实现类。其中NoOpPasswordEncoder是类是使用明文。而安全性最高,最常用的是BCryptPasswordEncoder加密类。
bcrypt是通过强哈希进行加密,每次加密的结果也不相同。它的安全性要高于MD5,当然,加密算法越安全,时常就越长。但是用户是感觉不到的。
那么如何将我们上一节完成的基于明文密码的验证转化为bcrpt的方式呢。其实很简单,只需要将password的前缀改成{bcrypt}即可。可能你也会好奇,如果想用其他的加密方式,那它对应的前缀该去哪里找呢。只需要全局搜索PasswordEncoderFactories这个工厂类,我们就能看到所以的前缀名。
四、获取当权登录用户
在传统的web系统中,我们将登录成功的用户存入session中,在需要的时候从session中获取用户,但是在Spring Security中我们如何获取当前已经登录的用户呢?
方法一:
-
SecurityContextHolder
他保留了iong的安全上下文SecurityContext,它计入了当前使用系统的用户信息。
-
SecurityContext
安全上下文,获取当前经过身份验证的主题和身份验证的请求令牌。
代码实现
@GetMapping("/loginUser1")
public UserDetails getCurrentUser() {
UserDetails principal = (UserDetails) SecurityContextHolder
.getContext() //获取上下文
.getAuthentication() //获取认证信息
.getPrincipal(); //获取当前用户登录信息
return principal;
}
查询结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iLfFSMPf-1673327903117)(Spring sercrity.assets/image-20221224132542826.png)]
方法二:
通过在控制层方法中注入Authentication(认证信息)来获取Principal。
代码实现:
@GetMapping("loginUser2")
public UserDetails getCurrentUser(Authentication authentication){
UserDetails principal = (UserDetails) authentication
.getPrincipal();
return principal;
}
调用结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1VZNwbdf-1673327903118)(Spring sercrity.assets/image-20221224132616271.png)]
方法三:
在控制层形参中注入userDetails用户登录信息,但是需要加入注解才能注入。
代码实现:
@GetMapping("/loginUser3")
public UserDetails getCurrentUser(@AuthenticationPrincipal UserDetails userDetails) {
return userDetails;
}
调用结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TLHcwBLH-1673327903118)(Spring sercrity.assets/image-20221224132507798.png)]
五、记住我功能实现
在很多的网站中,都会有RememberMe这个功能,这方便了用户在下一次登录时直接登录,避免了重复输入账户密码。Spring
Security针对于这个功能也帮助我们实现了。
方式一:使用token的方式
使用token的方式比较简单,他是通过将令牌存入到Cookie中。
原理图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u1d52QPn-1673327903119)(Spring sercrity.assets/image-20221224134741270.png)]
Token=MD5(username+分隔符+expiryTime+分隔符+password)
注意:这种方式不推荐使用,有严格是安全问题,密码保存在前端浏览器cookie中,容易被盗取破解。
实现:
http .formLogin()
.loginPage("/backend/login.html") //自定义登录页面
.loginProcessingUrl("/login") //自定义登录页面所提交的路径
.defaultSuccessUrl("/backend/index.html",true)
.passwordParameter("password")
.usernameParameter("username")
//在这里配置rememberMe
.and().rememberMe() //开去记住我功能
.tokenValiditySeconds(1209600) //token 失效时间,默认是两周
.rememberMeParameter("remember-me") //前端提交请求参数 value可选 true yes 1 on 都可以
.and()
.authorizeRequests().antMatchers("/backend/login.html").permitAll() //放行登录页面
.anyRequest().authenticated();
前台代码
<div>
<input type="checkbox" name="remember-me" value="true">记住我
</div>
方法二:持久化Token生成的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Jgvqtsm-1673327903119)(Spring sercrity.assets/image-20221224144214754.png)]
存入数据可的Token包含:
token:每次访问都会重新生成
series:登录序列号,用户输入用户名与密码登陆时,该值都会重新生成。使用remember-me功能,该值保持不变。
expiryTime : token 过期时间。
CookieValue=encode(series+token)
实现:
1.在securityConfig配置类中创建方法
@Autowired
DataSource dataSource;
@Bean
public PersistentTokenRepository getPersistentTokenRepository(){
//1.创建一个PersistentTokenRepository的实现类
JdbcTokenRepositoryImpl jdbcTokenRepository =new JdbcTokenRepositoryImpl();
//2.设置数据源
jdbcTokenRepository.setDataSource(dataSource);
//3.启动时自动创建异常表, 第一次启动设置为 true 第二次启动设置为 false或者注释掉
jdbcTokenRepository.setCreateTableOnStartup(true);
//返回
return jdbcTokenRepository;
}
2.配置类
http .formLogin()
.loginPage("/backend/login.html")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/backend/index.html",true)
.passwordParameter("password")
.usernameParameter("username")
.and().rememberMe()
.tokenValiditySeconds(1209600)
.rememberMeParameter("remember-me")
//设置tokenRepository
.tokenRepository(getPersistentTokenRepository())
.and()
.authorizeRequests().antMatchers("/backend/login.html").permitAll()
.anyRequest().authenticated();
将Token存入到前台浏览器容易被盗取。那么如何避免这个问题那。我们在重要的aip上加一层限制,让与remember-me方式登录的用户需要进一步认证。例如百度云网盘在删除文件时的验证。
代码:
//获取认证的信息
Authentication authentication =SecurityContextHolder.getContext().getAuthentication();
//如果返回true这说明登录认证信息来源于自动登录
boolean flag = RememberMeAuthenticationToken.class.isAssignableFrom(authentication.getClass());
if(flag){
//如果时自动登录则将抛出此异常,spring security框架将会捕获并跳转到登录页面重新登录
throw new RememberMeAuthenticationException("认证来源于RememberMe");
}
六、自定义登录成功异常处理类
在某些场景下,用户登录成功或失败的情况下用户需要执行一些后续操作,比如登录日志的搜集,或者在前后端分类项目中,无论用户登录成功和失败后需要给前台页面返回对应的错误信息,有前台主导登录成功或失败的页面跳转,这个时候需要要用到AuthentiactionSuccessHandler与Authentication Failure Handler。
自定义成功处理:
实现SuthenticationSuccessHandler接口,并重写onAuthenticationSuccess()方法。
自定义失败处理:
实现SuthenticationFailureHandler接口,并重写onAuthenticationFailure()方法。
代码实现:
-
创建一个Service并继承成功与失败相对应的接口,并实现方法
/** * @author lihaojie * @date 2022/12/25 11:27 **/ @Service public class MyAuthenticationService implements AuthenticationFailureHandler, AuthenticationSuccessHandler { /** * 登录成功处理类 * * @param httpServletRequest * @param httpServletResponse * @param authentication */ @Override public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { //登录成功后跳转到前端 //可以记录一下ip 等用户数据 System.out.println("登录成功"); } /** * 登录失败处理类 * * @param httpServletRequest * @param httpServletResponse * @param e */ @Override public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { System.out.println("登录失败"); } }
-
将自定的Service注入到SecurityConfig配置类并配置
/** * 在spring security 配置类中 **/ @Autowired private MyAuthenticationService myAuthenticationService; @Override protected void configure(HttpSecurity http) throws Exception { http .formLogin() //开启表单 //配置自定义的登录后的处理类 .successHandler(myAuthenticationService) .failureHandler(myAuthenticationService) }
七、Session管理
Spring Security可以与Spring Session库配合使用,只需要做一些简单的配置就可以实现一些功能,例如:会话过期,一个账号只能同时在线一个,集群session等。
1.会话超时
(1)配置session会话超时时间,默认为30分钟,但是Spring Boot中会话超时时间至少60秒
#session设置
#配置session超时时间
server.servlet.session.timeout=60
当session超时后,默认跳转到登录页面
(2)自定义session超时后的地址
http.sessionManagement()//设置session管理
.invalidSessionUrl("/toLoginPage") //session无效后跳转的路径,默认是登陆页面
2.并发控制
并发控制即同一个账号在线个数,同一个账号在线个数如果设置为1,这表示该账号在同一时间内只能有一个有效登录,如果同意账号又在其他地方登录,那么就将上次登录的会话过期,即后面的登录会踢掉前面的登录。
(1)设置最大会话数量
http.sessionManagement().invalidSessionUrl("/toLoginPage") //当session超时的跳转路径
.maximumSessions(1) //设置session最大数量
.expiredUrl("/toLoginPage"); //session过期(被踢掉)的跳转路径
(2)设置最大会话数量
http.sessionManagement().invalidSessionUrl("/toLoginPage") //当session超时的跳转路径
.maximumSessions(1) //设置session最大数量
.maxSessionsPreventsLogin(true) //当打到最大数量后将阻止新的登录,
//这意味着expiredUrl将失效
.expiredUrl("/toLoginPage"); //session过期(被踢掉)的跳转路径
3.基于redis的session共享
在分布式的架构中,我们通过Nginx实现自己的服务代理,那么再一次登录后可能会跨集群调用,而每跨一次都需要用户登录一次。那如何解决此问题?可以通过redis做session共享,Spring Security在做获取session时都会从redis中获取。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q0yjIB5E-1673327903120)(Spring sercrity.assets/image-20221225184305804.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t3GyxniU-1673327903121)(Spring sercrity.assets/image-20221225184325172.png)]
(1)引入依赖
<!--基于redis实现session共享-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
(2)设置session储存类型
#使用redis共享session
spring.session.store-type=redis
八、csrf防护机制
1.csrf介绍
(1)csrf简介
CSFF(Cross-site request forgery) ,中文名称:跨站请求伪造。你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求,CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交网站分别爆出CSRF漏洞,如: NYTime.om(纽约时报)、Metafilter (一个大型的BLG网站),Youube和度Hl…而现在,互联网上的许多站点仍对此毫无防备,以至于安全业界称CSRF为”沉睡的巨人”。
(2)csrf原理图
从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成三个步骤:
1.登录受信任网站A,并在本地生成Cookie。
2.在不登出A的情况下,访问危险网站B。
3.触发网站B中的一些元素
(3) CSRF的防御策略
在业界目前防御CSRF 攻击主要有三种策略:验证 HTTP Referer 字段,在请求地址中添加oken 并验证,在 HTTP 头中自定义属性并验证。
①验证HTTP Referer字段
根据 HTTP 协议,在 HTTP头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址,在通常情况下,访问一个安全受限页面的请求来自于同一个网站,在后台请求验证其 Referer 值,如果是以自身安全网站开头的域名,则说明该请求是是合法的。如果Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
②在请求地址中添加 token 并验证
CSRF攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于cookie 中,因此里客可以在不知道这些验证信息的情况下直接利用用户自己的cookie 来通过安全验证,要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦载器来验证这个token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求3在HTTP头中自定义属性并验证。这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。
2.Spring Security实现csrf
Spring Security默认开始csrf,并对所有post起作用。
(1)前端在提交时需要携带token
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>记住我
(2)配置忽略的路径
http.csrf().ignoringAntMatchers("/url")
九、跨域与CORS
跨域,实质上是浏览器的一种保护处理,如果产生了跨域,服务器在返回结果时就会被浏览器拦截(注意:此时请求是可以正常发起的,只是浏览器对其进行了拦截),导致响应的内容不可用.产生跨域的几种情况有一下:
- 请求域名发生改变(主域名,副域名任意一个改变都可)
- 请求协议发生改变(http --> https)
- 请求端口发生改变(8080 -->8090)
1.解决跨域
1.JSONP
浏览器允许一些带src属性的标签跨域,也就是在某些标签的src属性上写ur地址是不会产生跨域问题2.CORS解决跨域
CORS是一个W3C标准,全称是"跨域资源共享”(Cross-origin resoure sharing) CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,E浏览器不能低于IE10。浏览器在发起真正的请求之前,会发起一个OPTIONS类型的预检请求,用于请求服务器是否允许跨域,在得到许可的情况下才会发起请求
/**
*跨城配置信息源
*/
public CorsConfiqurationSource corsConfigurationSource() f
CorsConfiguration corsConfiguration = new CorsConfiguration();
//允许跨域的站点
corsConfiguration.addAllowedOrigin(*");
//允许跨域的http方法
corsConfiguration.addAllowedMethod("*");
// 允许跨域的请求头
corsConfiquration.addAllowedHeader("*);
// 允许带凭证
corsConfiguration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
// 对所有ur1都生效
urlBasedCorsConfigurationSource.registerCorsConfiguration( path: "/**n, corsConfiguration);
return urlBasedCorsConfigurationSource;
//开启跨域支持
http.cors().confiqurationSource(corsConfiqurationSource());
授权
一、内置权限表达式
Spring Security 使用Spring EL来支持,主要用于Web访问和方法安全上,可以通过表达式来判断是否具有访问权限.下面是SpringSecurity常用的内置表达式.ExpressionUrlAuthorizationConfigurer定义了所有的表达式:
表达式 | 说明 |
---|---|
permitAll | 指定任何人都允许访问。 |
denyAll | 指定任何人都不允许访问 |
anonymous | 指定匿名用户允许访问。 |
rememberMe | 指定已记住的用户允许访问。 |
authenticated | 指定任何经过身份验证的用户都允许访问,不包含anonymous |
fullyAuthenticated | 指定由经过身份验证的用户允许访问,不包含anonymous和rememberMe |
hasRole(role) | 指定需要特定的角色的用户允许访问,会自动在角色前面插入ROLE_“ |
hasAnvRole([role1,role2]) | 指指定需要任意一个角色的用户允许访问,会自动在角色前面插入ROLE_“ |
hasAuthority(authority) | 指定需要特定的权限的用户允许访问 |
hasAnyAuthority([authority,authority]) | 指定需要任意一个权限的用户允许访问 |
haslpAddress(ip) | 指定需要特定的IP地址可以访问 |
二、基于URL的权限控制
1.配置类
//开启权限控制
http.authorizeRequests().antMatchers("/employee/**") //对"/employee/**"开启权限控制
.hasRole("ADMIN"); //指定特定用户(ADMIN)访问
http.authorizeRequests().antMatchers("/product/**") //对”/product/**”开启权限控制
.access("hasAnyRole('ADMIN','PRODUCT') and hasIpAddress('127.0.0.1')"); //对于多个限定可以使用el表达式
http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);//myAccessDeniedHandler自定义权限不足处理类
2.myAccessDeniedHandler自定义权限不足处理类
/**
* 自定义权限不足处理类
**/
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setContentType("text/html;charset=UTF-8");
httpServletResponse.getWriter().write("权限不足");
}
}
3.赋予用户权限
/**
* 使用数据库账号登录
**/
@Service
public class MyUserDetailsServiceService implements UserDetailsService {
@Autowired
private EmployeeService employeeService;
/**
* 设置为从数据库获取账户与密码
*
* 我们通过用户名查询不到用户,则抛出异常,如果查到了用户,我们需要将查询到丢username与password等一些用户状态的参数进行封装,封装为一个UserDetails
* 返回给框架,框架会自己将数据库的用户密码与前台传入的做对比
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Employee employeeDb=employeeService.findByUsername(username);
if(employeeDb==null){
throw new UsernameNotFoundException("用户没找到:"+username);
}
//创建权限集合
Collection<GrantedAuthority> authorities =new ArrayList<>();
//赋予权限 赋予权限时要加REOLE_前缀,配置时不用(系统给我们加)
if(username.equalsIgnoreCase("admin")){
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}else {
authorities.add(new SimpleGrantedAuthority("ROLE_OTHER"));
}
//创建UserDetails用户详情对象并返回给框架
UserDetails userDetails = new org.springframework.security.core.userdetails.User
(username,
"{bcrypt}"+ employeeDb.getPassword(),
authorities); //用户权限集合
return userDetails;
}
}
三、方法粒度的权限控制
针对方法粒度的访问控制比较复杂,Spring Security 提供了4中注解,其中Pre开头的为方法调用前的控制,Post开头的为方法调用后,对返回值的控制。在使用注解进行方法权限控制时,我们需要开启方法权限控制:
// spring security 配置类
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启方法权限控制
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}
1. @PreAuthorize() 注解
在方法调用之前,对方法权限进行控制。
(1)针对方法参数控制
@PreAuthorize("#id<3") //Controller方法参数控制,id<3的才能被访问
(2)对用户角色控制
@PreAuthorize("hasRole('ADMIN')") //调用Controller方法的角色权限控制,只有ADMIN用户才能访问
注意:这里算是设置权限控制角色,所以不加前缀 “ROLE_”
2. @PostAuthorize() 注解
注解适合有返回值的方法权限校验。
//对返回值进行权限校验,只能自己查询自己的信息
@PostAuthorize("returnObject.username==authentication.principal.username")
returnObject : 为方法返回的结果对象。
authentication : 身份验证信息
3. @PreFilter()注解
在方法调用前,对于集合类的参数进行过滤,过滤掉不符合的数据,保留符合的数据。
//过滤掉ids集合中,id不等于0的
@PreFilter(filterTarget = "ids",value = "filterObject==0")
filterTarget : 要过滤的目标参数,一般时集合
filterObject :为filterTarget 中的一个元素
4. @PostFilter()注解
在方法调用后,对方法的结果进行过滤。
//提出所有id为奇数的结果
@PostFilter("fileterObject.id%2==0")
ending……