创建自定义过滤器调用安全性元数据类,实现FilterInvocationSecurityMetadataSource
接口
@Component
public class CustomFilterInvocationSecurityMetadata implements FilterInvocationSecurityMetadataSource {
@Autowired
MenuServiceImpl menuService;
AntPathMatcher antPathMatcher=new AntPathMatcher();
@Override
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
String requestUrl = ((FilterInvocation) o).getRequestUrl();
//获取菜单的所有权限
List<Menu> menus=menuService.getAllMenuWithRole();
for (Menu menu : menus) {
//判断当前请求接口路径是否和菜单中路径一致
if(antPathMatcher.match(menu.getUrl(),requestUrl)){
//如果一致则进入,并创建一个角色集合
List<Role> roles=menu.getRoles();
String[] strings=new String[roles.size()];
for (int i=0;i<roles.size();i++){
strings[i]=roles.get(i).getName();
}
System.out.println(strings);
return SecurityConfig.createList(strings);
}
}
return SecurityConfig.createList("ROLE_LOGIN");
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> aClass) {
return false;
}
}
创建网址访问决策管理器类,实现AccessDecisionManager
接口
public class UrlAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication auth, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
for (ConfigAttribute configAttribute : collection) {
String needROle = configAttribute.getAttribute();
if("ROLE_LOGIN".equals(needROle)){
if (auth instanceof AnonymousAuthenticationToken){
throw new AccessDeniedException("尚未登陆,请登录");
}else {
return;
}
}
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
for (GrantedAuthority authority : authorities) {
if(authority.getAuthority().equals(needROle)){
return;
}
}
}
throw new AccessDeniedException("权限不足,请访问管理员");
}
@Override
public boolean supports(ConfigAttribute configAttribute) {
return true;
}
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}
注入urlAccessDecisionManager
和customFilterInvocationSecurityMetadata
@Autowired
CustomFilterInvocationSecurityMetadata customFilterInvocationSecurityMetadata;
@Autowired
UrlAccessDecisionManager urlAccessDecisionManager;
修改HttpSecurity
配置方法
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//.anyRequest().authenticated()//任何请求都已认证
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O object) {
object.setAccessDecisionManager(urlAccessDecisionManager);
object.setSecurityMetadataSource(customFilterInvocationSecurityMetadata);
return object;
}
})
.and()
...........省略,详情看上两篇................
没有认证时,在这里处理结果,不要重定向,告诉前端
/*没有认证时,在这里处理结果,不要重定向*/
.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out=resp.getWriter();
RespBean respBean = RespBean.error("访问失败");
if (e instanceof InsufficientAuthenticationException){
respBean.setMsg("请求失败,请联系管理员");
}
out.write(new ObjectMapper().writeValueAsString(respBean));
out.flush();
out.close();
}
});