package com.kidgrow.authclient.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.kidgrow.authclient.properties.SecurityProperties; import com.kidgrow.authclient.util.AuthUtils; import com.kidgrow.common.constant.CommonConstant; import com.kidgrow.common.context.ClientContextHolder; import com.kidgrow.common.model.SysMenu; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.util.AntPathMatcher; import java.util.List; import java.util.stream.Collectors; /** * 石家庄喜高科技有限责任公司 版权所有 © Copyright 2020
* * @Description: 请求权限判断默认service
* @Project:
* @CreateDate: Created in 2020/2/13 11:46
* @Author: liuke */ @Slf4j public abstract class DefaultPermissionServiceImpl { @Autowired private SecurityProperties securityProperties; private AntPathMatcher antPathMatcher = new AntPathMatcher(); /** * 查询当前用户拥有的资源权限 * @param roleCodes 角色code列表,多个以','隔开 * @return */ public abstract List findMenuByRoleCodes(String roleCodes); public boolean hasPermission(Authentication authentication, String requestMethod, String requestURI) { // 前端跨域OPTIONS请求预检放行 也可通过前端配置代理实现 if (HttpMethod.OPTIONS.name().equalsIgnoreCase(requestMethod)) { return true; } if (!(authentication instanceof AnonymousAuthenticationToken)) { //判断是否开启url权限验证 if (!securityProperties.getAuth().getUrlPermission().getEnable()) { return true; } //超级管理员admin不需认证 String username = AuthUtils.getUsername(authentication); if (CommonConstant.ADMIN_USER_NAME.equals(username)) { return true; } OAuth2Authentication auth2Authentication = (OAuth2Authentication)authentication; //判断应用黑白名单 if (!isNeedAuth(auth2Authentication.getOAuth2Request().getClientId())) { return true; } //判断不进行url权限认证的api,所有已登录用户都能访问的url for (String path : securityProperties.getAuth().getUrlPermission().getIgnoreUrls()) { if (antPathMatcher.match(path, requestURI)) { return true; } } List grantedAuthorityList = (List) authentication.getAuthorities(); if (CollectionUtil.isEmpty(grantedAuthorityList)) { log.warn("角色列表为空:{}", authentication.getPrincipal()); return false; } //保存租户信息 String clientId = auth2Authentication.getOAuth2Request().getClientId(); // String tenantId=""; // //保存租户id,租户id根据业务尽进行替换 // switch (clientId){ // case "hospital": // tenantId="1"; // break; // case "webApp": // tenantId="webApp"; // break; // } // TenantContextHolder.setTenant(tenantId); ClientContextHolder.setClient(clientId); String roleCodes = grantedAuthorityList.stream().map(SimpleGrantedAuthority::getAuthority).collect(Collectors.joining(", ")); List menuList = findMenuByRoleCodes(roleCodes); /* *需求:h端 没有进行配置url的通过,剩下的进行验证 * */ //根据h端进行验证 if("hospital".equals(clientId)){ if(!menuList.isEmpty()){ List collect = menuList.stream().map(SysMenu::getUrl).collect(Collectors.toList()); if(collect.contains(requestURI)){ for (SysMenu menu : menuList) { if (StringUtils.isNotEmpty(menu.getUrl()) && antPathMatcher.match(menu.getUrl(), requestURI)) { if (StrUtil.isNotEmpty(menu.getPathMethod())) { if(!requestMethod.equalsIgnoreCase(menu.getPathMethod())){ continue; } return requestMethod.equalsIgnoreCase(menu.getPathMethod()); } } } }else { //不在配置menu集合里面的放行 return true; } }else{ return true; } } for (SysMenu menu : menuList) { if (StringUtils.isNotEmpty(menu.getUrl()) && antPathMatcher.match(menu.getUrl(), requestURI)) { if (StrUtil.isNotEmpty(menu.getPathMethod())) { if(!requestMethod.equalsIgnoreCase(menu.getPathMethod())){ continue; } return requestMethod.equalsIgnoreCase(menu.getPathMethod()); } else { return true; } } } } return false; } /** * 判断应用是否满足白名单和黑名单的过滤逻辑 * @param clientId 应用id * @return true(需要认证),false(不需要认证) */ private boolean isNeedAuth(String clientId) { boolean result = true; //白名单 List includeClientIds = securityProperties.getAuth().getUrlPermission().getIncludeClientIds(); //黑名单 List exclusiveClientIds = securityProperties.getAuth().getUrlPermission().getExclusiveClientIds(); if (includeClientIds.size() > 0) { result = includeClientIds.contains(clientId); } else if(exclusiveClientIds.size() > 0) { result = !exclusiveClientIds.contains(clientId); } return result; } }