@Component
public class DynamicSecurityFilter extends AbstractSecurityInterceptor implements Filter {
@Autowired
private MyFilter dynamicSecurityMetadataSource;
// @Autowired
private IgnoreUrlsConfig ignoreUrlsConfig = new IgnoreUrlsConfig();
@Autowired
public void setMyAccessDecisionManager(MyAccessDecisionManager dynamicAccessDecisionManager) {
super.setAccessDecisionManager(dynamicAccessDecisionManager);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
FilterInvocation fi = new FilterInvocation(servletRequest, servletResponse, filterChain);
//OPTIONS请求直接放行
if(request.getMethod().equals(HttpMethod.OPTIONS.toString())){
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
return;
}
//白名单请求直接放行
PathMatcher pathMatcher = new AntPathMatcher();
for (String path : ignoreUrlsConfig.getUrls()) {
if(pathMatcher.match(path,request.getRequestURI())){
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
return;
}
}
//此处会调用AccessDecisionManager中的decide方法进行鉴权操作
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
@Override
public void destroy() {
}
@Override
public Class<?> getSecureObjectClass() {
return FilterInvocation.class;
}
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return dynamicSecurityMetadataSource;
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig {
Http403ForbiddenEntryPoint unauthorizedHandler =new Http403ForbiddenEntryPoint();
@Autowired
MyFilter myFilter;
@Autowired
MyAccessDecisionManager myAccessDecisionManager;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf->csrf.disable())
.userDetailsService(userDetailsService())
.httpBasic(withDefaults())
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
// .withObjectPostProcessor()
// .withObjectPostProcessor(new ObjectPostProcessor<BasicAuthenticationFilter>() {
// @Override
// public <O extends BasicAuthenticationFilter> O postProcess(O object) {
// object.setSecurityContextRepository(new HttpSessionSecurityContextRepository());
object.setAccessDecisionManager(myAccessDecisionManager);
object.setSecurityMetadataSource(myFilter);
// // object.setPublishAuthorizationSuccess(true);
// return object;
// }
// })
// 无需验证路径
// .requestMatchers("/public/**").permitAll()
//
// //.requestMatchers("/hello/**").permitAll()
// // 无需验证登录路径
// .requestMatchers("/login").permitAll()
// // 拥有权限才可访问
// .requestMatchers("/user/**").hasRole("user")//.hasAuthority("USER1")
// .requestMatchers("/admin/**").hasRole("admin")//.hasAuthority("USER1")
// .requestMatchers("/getBooks").hasRole("admin")//.hasAuthority("USER1")
// .requestMatchers("/aaa").hasRole("admin")//.hasAuthority("USER1")//没有权限的时候提示是404
// .requestMatchers("/user").hasAuthority("getAllUser")
// // 拥有任一权限即可访问
// .requestMatchers("user").hasAnyAuthority("1","2")
// // 角色类似,hasRole(),hasAnyRole()
// .anyRequest().authenticated()
)
// 自定义异常处理 自定义后不会调到登录界面,不知道为什么
// .exceptionHandling(exception -> exception
// .authenticationEntryPoint(unauthorizedHandler)
// //权限不足处理
// .accessDeniedHandler(new AccessDeniedHandlerImpl())
// )//
// .logout(httpSecurityLogoutConfigurer -> {
// httpSecurityLogoutConfigurer
// .logoutUrl("/public/logout")
// .logoutSuccessUrl("public/logoutSuccess");
// // .logoutSuccessHandler(myLogoutSuccessHandle);
// })
.formLogin(withDefaults())
;
http.addFilterBefore(filter, FilterSecurityInterceptor.class);
return http.build();
}
@Autowired DynamicSecurityFilter filter;
@Bean
public UserDetailsService userDetailsService() {
return new MyUserDetailsService();
}
// @Bean
// public InMemoryUserDetailsManager userDetailsService() {
// UserDetails user = User.withDefaultPasswordEncoder()
// .username("user")
// .password("1234")
// .roles("USER1","USER2")
// //.authorities("USER1")
// .build();
// return new InMemoryUserDetailsManager(user);
// }
@Bean
PasswordEncoder getPasswordEncoder(){
//new BCryptPasswordEncoder();
return NoOpPasswordEncoder.getInstance();
}
}
// @Bean
// public UserDetailsManager users(DataSource dataSource) {
// UserDetails user = User.withDefaultPasswordEncoder()
// .username("admin")
// .password("123")
// .roles("USER1")
// .build();
// JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
// users.createUser(user);
// return users;
// }
// @Bean
// public InMemoryUserDetailsManager userDetailsService() {
// UserDetails user = User.withDefaultPasswordEncoder()
// .username("user")
// .password("123")
// .roles("USER1","USER2")
// //.authorities("USER1")
// .build();
// return new InMemoryUserDetailsManager(user);
// }
@Component
public class MyFilter implements FilterInvocationSecurityMetadataSource {
AntPathMatcher antPathMatcher = new AntPathMatcher();
@Autowired
MenuRepository menuRepository;
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
String requestUrl = ((FilterInvocation)object).getRequestUrl();
List<Menu> allMenus = menuRepository.findAll();
for (Menu menu : allMenus) {
if (antPathMatcher.match(menu.getPattern(), requestUrl)) {
List<Role> roles = menu.getRoles();
String[] roleArr = new String[roles.size()];
for (int i = 0; i < roleArr.length; i++) {
roleArr[i] = roles.get(i).getName();
}
// org.springframework.security.access.SecurityConfig.createList()
return org.springframework.security.access.SecurityConfig.createList(roleArr);
}
}
return org.springframework.security.access.SecurityConfig.createList("ROLE_LOGIN");
// return null;
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {
/**
* @param authentication 保存了当前登录用户的信息(已有哪些角色)
* @param o
* @param collection 需要哪些角色,和authentication对比判断
* @throws AccessDeniedException
* @throws InsufficientAuthenticationException
*/
@Override
public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
for (ConfigAttribute attribute : collection) {//遍历collection,就是你需要的角色
if ("ROLE_LOGIN".equals(attribute.getAttribute())) { //登录之后就可以访问
if (authentication instanceof AnonymousAuthenticationToken) { //如果是匿名用户,说明没登录,抛异常
throw new AccessDeniedException("非法请求!");
} else {
return;
}
}
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();//已经存在的角色/
for (GrantedAuthority authority : authorities) {
if (authority.getAuthority().equals(attribute.getAttribute())) { //如果存在你需要的角色,直接return
return;
}
}
}
throw new AccessDeniedException("非法请求!");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}