ludc
2023-09-19 8381325223bee254168855b1b697db31fc591b9e
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
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package com.vci.ubcs.auth.granter;
 
import com.vci.ubcs.auth.service.BladeUserDetails;
import com.vci.ubcs.auth.utils.TokenUtil;
import com.vci.ubcs.system.user.entity.User;
import com.vci.ubcs.system.user.entity.UserInfo;
import com.vci.ubcs.system.user.entity.UserOauth;
import com.vci.ubcs.system.user.feign.IUserClient;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import com.vci.ubcs.auth.constant.AuthConstant;
import org.springblade.core.social.props.SocialProperties;
import org.springblade.core.social.utils.SocialUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.stereotype.Component;
 
import javax.servlet.http.HttpServletRequest;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
 
/**
 * 第三方登录认证类
 *
 * @author Chill
 */
public class SocialTokenGranter extends AbstractTokenGranter {
    private static final String GRANT_TYPE = "social";
    private static final Integer AUTH_SUCCESS_CODE = 2000;
 
    private final IUserClient userClient;
    private final SocialProperties socialProperties;
 
    protected SocialTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, IUserClient userClient, SocialProperties socialProperties) {
        super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.userClient = userClient;
        this.socialProperties = socialProperties;
    }
 
    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        // 请求头租户信息
        HttpServletRequest request = WebUtil.getRequest();
        String tenantId = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_ID);
 
        Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
        // 开放平台来源
        String sourceParameter = parameters.get("source");
        // 匹配是否有别名定义
        String source = socialProperties.getAlias().getOrDefault(sourceParameter, sourceParameter);
        // 开放平台授权码
        String code = parameters.get("code");
        // 开放平台状态码
        String state = parameters.get("state");
 
        // 获取开放平台授权数据
        AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
        AuthCallback authCallback = new AuthCallback();
        authCallback.setCode(code);
        authCallback.setState(state);
        AuthResponse authResponse = authRequest.login(authCallback);
        AuthUser authUser;
        if (authResponse.getCode() == AUTH_SUCCESS_CODE) {
            authUser = (AuthUser) authResponse.getData();
        } else {
            throw new InvalidGrantException("social grant failure, auth response is not success");
        }
 
        // 组装数据
        UserOauth userOauth = Objects.requireNonNull(BeanUtil.copy(authUser, UserOauth.class));
        userOauth.setSource(authUser.getSource());
        userOauth.setTenantId(tenantId);
        userOauth.setUuid(authUser.getUuid());
 
        // 远程调用,获取认证信息
        R<UserInfo> result = userClient.userAuthInfo(userOauth);
        BladeUserDetails bladeUserDetails;
        if (result.isSuccess()) {
            User user = result.getData().getUser();
            Kv detail = result.getData().getDetail();
            if (user == null || user.getId() == null) {
                throw new InvalidGrantException("social grant failure, user is null");
            }
            bladeUserDetails = new BladeUserDetails(user.getId(),
                tenantId, result.getData().getOauthId(), user.getName(), user.getRealName(), user.getDeptId(), user.getPostId(), user.getRoleId(), Func.join(result.getData().getRoles()), Func.toStr(userOauth.getAvatar(), TokenUtil.DEFAULT_AVATAR),
                userOauth.getUsername(), AuthConstant.ENCRYPT + user.getPassword(), detail, true, true, true, true,
                AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(result.getData().getRoles())));
        } else {
            throw new InvalidGrantException("social grant failure, feign client return error");
        }
 
        // 组装认证数据,关闭密码校验
        Authentication userAuth = new UsernamePasswordAuthenticationToken(bladeUserDetails, null, bladeUserDetails.getAuthorities());
        ((AbstractAuthenticationToken) userAuth).setDetails(parameters);
        OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
 
        // 返回 OAuth2Authentication
        return new OAuth2Authentication(storedOAuth2Request, userAuth);
    }
 
}