在使用hasRole("admin")这种方式配置权限时使用RoleHierarchy实现权限继承
是可以的,但是使用了数据库动态配置权限后继承失效,amdin不能访问user
下的接口了
@Configuration
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
SysUserServiceImpl sysUserService;
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
log.info("run custom user service");
auth.userDetailsService(sysUserService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
log.info("run security configuation");
http.authorizeRequests()
// .antMatchers("/admin/**").hasRole("admin")
// .antMatchers("/menu/**").hasRole("user")
// .antMatchers("/user/**").hasRole("user")
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O object) {
object.setSecurityMetadataSource(cfisms());
object.setAccessDecisionManager(cadm());
return object;
}
})
.and()
.formLogin()
.loginProcessingUrl("/login").permitAll()
.and()
.csrf().disable();
}
@Bean
RoleHierarchy roeHierarchy() {
RoleHierarchyImpl roeImpl = new RoleHierarchyImpl();
String hierarchy = "ROLE_admin > ROLE_user";
roeImpl.setHierarchy(hierarchy);
return roeImpl;
}
@Bean
CustomFilterInvocationSecurityMetadataSource cfisms() {
return new CustomFilterInvocationSecurityMetadataSource();
}
@Bean
CustomAccessDecisionManager cadm() {
return new CustomAccessDecisionManager();
}
}
user
@Component
@Slf4j
public class SysUser implements Serializable,UserDetails{
/**
*
*/
private static final long serialVersionUID = 1L;
private String id;
private String username;
private String password;
private String trueName;
private String note;
private String avator;
private String tel;
private String address;
private Integer pageNo;
private Integer pageSize;
private List<Role> roles;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
log.info("password:"+password);
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTrueName() {
return trueName;
}
public void setTrueName(String trueName) {
this.trueName = trueName;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public String getAvator() {
return avator;
}
public void setAvator(String avator) {
this.avator = avator;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getPageNo() {
return pageNo;
}
public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return SysUser.class.getName().toString();
}
// security getter and setter
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// get user permissions that already have
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
for(Role role : roles) {
authorities.add(new SimpleGrantedAuthority(role.getRole()));
log.info(role.getRole());
}
return authorities;
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return true;
}
}
自定义FilterInvocationMetadataSource
@Component
@Slf4j
public class CustomFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
AntPathMatcher antPathMatcher = new AntPathMatcher();
@Autowired
ServiceUrlMapper serviceUrlMapper;
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
//use AntPathMatcher matching rule
String requestUrl = ((FilterInvocation)object).getRequestUrl();
log.info("request url:"+requestUrl);
//select all service url
List<ServiceUrl> urls = serviceUrlMapper.select();
for(ServiceUrl url : urls) {
if(antPathMatcher.match(url.getUrl(), requestUrl)) {
List<Role>roles = url.getRoles();
String[]roleArr = new String[roles.size()];
for(int i=0; i<roleArr.length; i++) {
roleArr[i] = roles.get(i).getRole();
log.info("role:"+roleArr[i]);
}
//return role info
return SecurityConfig.createList(roleArr);
}
}
return SecurityConfig.createList("ROLE_LOGIN");
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
}
自定义AccessDecisionManager
@Component
@Slf4j
public class CustomAccessDecisionManager implements AccessDecisionManager {
/**
* decide current user permissions
* @param authentication user login info
* @param object FilterInvacation , it can obtain request info
* @param configAttributes FilterInvocationSecurityMetadataSource return by getAttributes
*/
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
Collection<? extends GrantedAuthority> auths = authentication.getAuthorities();
for(ConfigAttribute configAttribute : configAttributes) { //configAttributes from customFilterInvocationMetadataSource
if("ROLE_LOGIN".equals(configAttribute.getAttribute())&&auths instanceof UsernamePasswordAuthenticationToken) {
log.info("current user:ROLE_LOGIN");
return;
}
for(GrantedAuthority authority : auths) {
log.info("authority:"+authority.getAuthority());
if(configAttribute.getAttribute().equals(authority.getAuthority())) {
return;
}
}
}
throw new AccessDeniedException("权限不足");
}
@Override
public boolean supports(ConfigAttribute attribute) {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return true;
}
}
请问该怎么解决?