源代码
package club.zstuca.myzstu.filter;
import club.zstuca.myzstu.entity.Resource;
import club.zstuca.myzstu.entity.Role;
import club.zstuca.myzstu.mapper.ResourceMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import java.util.Collection;
import java.util.List;
/**
* @Author ShenTuZhiGang
* @Version 1.0.0
* @Date 2020-03-07 21:57
*/
@Component
public class CustomFilterInvocationSecurityMetadataSource
implements FilterInvocationSecurityMetadataSource {
AntPathMatcher antPathMatcher = new AntPathMatcher();
@Autowired
private ResourceMapper resourceMapper;
@Override
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
String ruquestUrl = ((FilterInvocation) o).getRequestUrl();
List<Resource> resources = resourceMapper.getAllResource();
for (Resource resource : resources){
if(antPathMatcher.match(resource.getPattern(),ruquestUrl)){
List<Role> roles = resource.getRoles();
String[] roleArr = new String[roles.size()];
for (int i = 0; i < roleArr.length;i++ ){
roleArr[i] = roles.get(i).getName();
}
return SecurityConfig.createList(roleArr);
}
}
return SecurityConfig.createList("ROLE_LOGIN");
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> aClass) {
return FilterInvocation.class.isAssignableFrom(aClass);
}
}
package club.zstuca.myzstu.filter;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.Collection;
/**
* @Author ShenTuZhiGang
* @Version 1.0.0
* @Date 2020-03-07 22:26
*/
@Component
public class CustomAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
Collection<? extends GrantedAuthority> auths = authentication.getAuthorities();
for(ConfigAttribute configAttribute:collection){
if("ROLE_LOGIN".equals(configAttribute.getAttribute())
&& authentication instanceof UsernamePasswordAuthenticationToken){
return;
}
for(GrantedAuthority authority : auths){
if(configAttribute.getAttribute().equals(authority.getAuthority())){
return;
}
}
}
throw new AccessDeniedException("权限不足");
}
@Override
public boolean supports(ConfigAttribute configAttribute) {
return true;
}
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}
package club.zstuca.myzstu.config;
import club.zstuca.myzstu.filter.CustomAccessDecisionManager;
import club.zstuca.myzstu.filter.CustomFilterInvocationSecurityMetadataSource;
import club.zstuca.myzstu.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
/**
* @Author ShenTuZhiGang
* @Version 1.0.0
* @Date 2020-03-07 16:48
*/
@Configuration
public class MyZSTUWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
IUserService iUserService;
@Bean
CustomFilterInvocationSecurityMetadataSource cfisms(){
return new CustomFilterInvocationSecurityMetadataSource();
}
@Bean
CustomAccessDecisionManager cadm(){
return new CustomAccessDecisionManager();
}
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth)throws Exception{
auth.userDetailsService(iUserService);
}
@Override
protected void configure(HttpSecurity http)throws Exception{
http.authorizeRequests()
.withObjectPostProcessor(
new ObjectPostProcessor<FilterSecurityInterceptor>() {
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O object) {
object.setSecurityMetadataSource(cfisms());
object.setAccessDecisionManager(cadm());
return object;
}
}
)
.antMatchers("/student/**")
.hasRole("student")
//.anyRequest()
//.authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.permitAll()
.and()
.csrf()
.disable();
}
}
教学资源
https://www.bilibili.com/video/av73730658?p=13
常见问题
参考文章
https://blog.csdn.net/qushapos/article/details/84940810