1:在springsecurity的配置文件中添加配制
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().sameOrigin();
//http.csrf().disable().cors().disable().headers().disable();
http.authorizeRequests().antMatchers("/", "/index", "/index.html",
"/toLoginPage").permitAll()
//.antMatchers("/static/**").permitAll()
// 这个配置就是告诉springsecurity,鉴权规则通过数据库动态加载
.anyRequest().access("@myRbacAuthention.hasPermission(request,authentication)")
/*.antMatchers("/vip1").hasRole("VIP1")
.antMatchers("/vip2").hasRole("VIP2")
.antMatchers("/vip3").hasRole("VIP3")*/;
// 开启表单认证
http.formLogin().loginProcessingUrl("/login").loginPage("/toLoginPage")
// 成功和失败的处理器
.successHandler(mySavedRequestAwareAuthenticationSuccessHandler)
.failureHandler(mySimpleUrlAuthenticationFailureHandler);
// 开启记住我,60秒
http.rememberMe().rememberMeParameter("rememberMe").tokenValiditySeconds(60);
// 开启注销
http.logout().logoutSuccessUrl("/");
// 处理登出的404错误!springsecurity的csrf(跨站请求伪造)保护
http.csrf().disable();
// 一个账户只能一个账号登陆,maxSessionsPreventsLogin(false)设置为false,标识第一个账号登陆后,
// 同一个账号还可以在其他地方登陆。只是将第一个挤下去,如果设置为true,则同一个账号就不能再次登陆了
http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(false)
.expiredSessionStrategy(new MySessionInfomantion());
}
2:自定义一个数据库加载资源鉴权的类
就是加载数据库中查询当前用户所有拥有的权限,然后和当前请求的资源进行比对,成功就返回true,否则就返回false
package com.itgo.springboot.springsecurity.config;
import com.itgo.springboot.springsecurity.mapper.SysUserMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* @Description: 自定义的权限表达式
* @auther: libiao
* @Email: libiao@163.com
* @Date: 2020-6-21 14:51
* @Copyright: (c) 2019-2022 XXXX公司
*/
@Component("myRbacAuthention")
public class MyRbacAuthention {
private AntPathMatcher antPathMatcher = new AntPathMatcher();
@Resource
private SysUserMapper sysUserMapper;
/**
* @Description: 判断当前用户是否存在某种权限
* @author libiao
* @Date 2020-6-21 14:52
* @Param
* @return
**/
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
Object principal = authentication.getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails) principal).getUsername();
// 通过用户名查询这个用户的所有权限
List<String> permissions = sysUserMapper.getAllPermissionByUesrName(username);
return permissions.stream().anyMatch(
url -> antPathMatcher.match(url, request.getRequestURI())
);
}
return false;
}
}
3:权限表达式
如果需要在方法上做权限表达式,需要配置注解,开启
在springsecurity的配置类中,开启注解
@EnableGlobalMethodSecurity(prePostEnabled = true)// 默认是false
package com.libiao.basicserver.service;
import com.libiao.basicserver.model.Person;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import static org.springframework.security.core.context.SecurityContextHolder.getContext;
@Service
public class MethodelService {
// 在执行方法之前判断当前用户是否存在admin这个角色
@PreAuthorize("hasRole('admin')")
public List<Person> findAll(){
return null;
}
// 在执行方法后,判断返回值
@PostAuthorize("returnObject.name == authentication.name")
public Person findOne(){
String authName =
getContext().getAuthentication().getName();
System.out.println(authName);
return new Person("admin");
}
// 过滤,执行方法之前,过滤掉,不满足要求的参数
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {
System.out.println();
}
// 执行方法后,过滤掉不满足要求的返回值
@PostFilter("filterObject.name == authentication.name")
public List<Person> findAllPD(){
List<Person> list = new ArrayList<>();
list.add(new Person("kobe"));
list.add(new Person("admin"));
return list;
}
}