forked from kidgrow-microservices-platform

bingbing
2020-10-27 1d5345f92dbd4aac2b5f68265921bb2529a71b8e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
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<br>
 *
 * @Description: 请求权限判断默认service<br>
 * @Project: <br>
 * @CreateDate: Created in 2020/2/13 11:46 <br>
 * @Author: <a href="4345453@kidgrow.com">liuke</a>
 */
@Slf4j
public abstract class DefaultPermissionServiceImpl {
 
    @Autowired
    private SecurityProperties securityProperties;
 
    private AntPathMatcher antPathMatcher = new AntPathMatcher();
 
    /**
     * 查询当前用户拥有的资源权限
     * @param roleCodes 角色code列表,多个以','隔开
     * @return
     */
    public abstract List<SysMenu> 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<SimpleGrantedAuthority> grantedAuthorityList = (List<SimpleGrantedAuthority>) 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<SysMenu> menuList = findMenuByRoleCodes(roleCodes);
            /*
             *需求:h端   没有进行配置url的通过,剩下的进行验证
             *
             */
            //根据h端进行验证
            if("hospital".equals(clientId)){
                if(!menuList.isEmpty()){
                    List<String> 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<String> includeClientIds = securityProperties.getAuth().getUrlPermission().getIncludeClientIds();
        //黑名单
        List<String> exclusiveClientIds = securityProperties.getAuth().getUrlPermission().getExclusiveClientIds();
        if (includeClientIds.size() > 0) {
            result = includeClientIds.contains(clientId);
        } else if(exclusiveClientIds.size() > 0) {
            result = !exclusiveClientIds.contains(clientId);
        }
        return result;
    }
}