shikeyin
2024-01-11 65da8373531677b1c37a98f53eaa30c892f35e5a
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
package com.iplatform.base.config;
 
import com.iplatform.base.SecuritySpi;
import com.iplatform.base.UserLoginCache;
import com.iplatform.base.service.LogServiceImpl;
import com.iplatform.base.support.LogAspect;
import com.iplatform.base.support.PlatformOperationInterceptor;
import com.iplatform.base.support.strategy.AbstractLoginStrategy;
import com.iplatform.base.support.strategy.LoginStrategyManager;
import com.iplatform.base.support.strategy.MobileOnceLoginStrategy;
import com.iplatform.base.support.strategy.WebOnceLoginStrategy;
import com.iplatform.core.PlatformConfiguration;
import com.walker.infrastructure.utils.StringUtils;
import com.walker.web.RestTemplateConfig;
import com.walker.web.RestTemplateFactory;
import com.walker.web.TokenGenerator;
import com.walker.web.WebAgentService;
import com.walker.web.agent.BrowserCapWebAgentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
import java.util.List;
 
/**
 * Web操作通用配置。
 * @author 时克英
 * @date 2022-11-21
 */
@Configuration
public class WebCommonConfig extends PlatformConfiguration implements WebMvcConfigurer {
 
    private TokenGenerator tokenGenerator;
 
    @Autowired
    public WebCommonConfig(TokenGenerator tokenGenerator){
        this.tokenGenerator = tokenGenerator;
    }
 
//    /**
//     * 测试登录回调。正式要注释掉,平台只允许业务配置一个!!!
//     * @return
//     * @date 2023-08-18
//     */
//    @Bean
//    public AfterLoginCallback afterLoginCallback(){
//        return new TestAfterLoginCallback();
//    }
 
    @Bean
    public LoginStrategyProperties loginStrategyProperties(){
        return new LoginStrategyProperties();
    }
 
    /**
     * 涉及用户安全的一些基本配置,如:登录错误次数、密码安全级别等。
     * @return
     * @date 2023-08-05
     */
    @Bean
    public SecurityUserProperties securityUserProperties(){
        return new SecurityUserProperties();
    }
 
    @Bean
    public LoginStrategyManager loginStrategyManager(UserLoginCache userLoginCache){
        LoginStrategyManager manager = new LoginStrategyManager();
        manager.setUserLoginCache(userLoginCache);
        return manager;
    }
 
    /**
     * 配置登录策略定义,PC端(同一用户)只能登录一次,无法重复登录。
     * <pre>
     *     1) 如果需要使用, 配置文件列表中,加上即可。
     * </pre>
     * @param userLoginCache
     * @param loginStrategyProperties
     * @param loginStrategyManager
     * @return
     * @date 2023-09-08
     */
    @Bean
    public WebOnceLoginStrategy webOnceLoginStrategy(UserLoginCache userLoginCache
            , LoginStrategyProperties loginStrategyProperties, LoginStrategyManager loginStrategyManager){
        List<String> enabledNameList = loginStrategyProperties.getLoginStrategyList();
        WebOnceLoginStrategy strategy = new WebOnceLoginStrategy();
        strategy.setUserLoginCache(userLoginCache);
        strategy.setTokenExpireWeb(loginStrategyProperties.getTokenExpireWeb());
        strategy.setName("PC端同一账号只能登录一次");
        this.setupRegisterLoginStrategy(enabledNameList, strategy, loginStrategyManager, WebOnceLoginStrategy.class.getName());
        return strategy;
    }
 
    /**
     * 配置登录策略定义,并注册到管理器中。
     * <p>移动端同一账号只能登录一次。</p>
     * @param userLoginCache
     * @param loginStrategyProperties
     * @return
     * @date 2023-07-11
     */
    @Bean
    public MobileOnceLoginStrategy mobileOnceLoginStrategy(UserLoginCache userLoginCache
            , LoginStrategyProperties loginStrategyProperties, LoginStrategyManager loginStrategyManager){
        List<String> enabledNameList = loginStrategyProperties.getLoginStrategyList();
        MobileOnceLoginStrategy strategy = new MobileOnceLoginStrategy();
        strategy.setUserLoginCache(userLoginCache);
        strategy.setTokenExpireMobile(loginStrategyProperties.getTokenExpireMobile());
        strategy.setName("移动端同一账号只能登录一次");
//        if(!StringUtils.isEmptyList(enabledNameList)){
//            for(String name : enabledNameList){
//                if(name.equals(strategy.getClass().getName())){
//                    strategy.setEnabled(true);
//                    loginStrategyManager.register(strategy);
//                    logger.info("启用了登录策略:{}", strategy.getName());
//                    break;
//                }
//            }
//        }
        this.setupRegisterLoginStrategy(enabledNameList, strategy, loginStrategyManager, MobileOnceLoginStrategy.class.getName());
        return strategy;
    }
 
    private void setupRegisterLoginStrategy(List<String> enabledNameList
            , AbstractLoginStrategy strategy, LoginStrategyManager loginStrategyManager, String strategyClazz){
        if(!StringUtils.isEmptyList(enabledNameList)){
            for(String name : enabledNameList){
                if(name.equals(strategyClazz)){
                    strategy.setEnabled(true);
                    loginStrategyManager.register(strategyClazz, strategy);
                    logger.info("启用了登录策略:{}", strategy.getName());
                    break;
                }
            }
        }
    }
 
    /**
     * TCP通信模块配置内容,迁移到base模块中,因为前端要获取websocket.uri,该接口必须在基础模块,否则会严重依赖tcp。
     * @return
     * @date 2023-04-17
     */
    @Bean
    public TcpProperties tcpProperties(){
        return new TcpProperties();
    }
 
    /**
     * 统一拦截Web操作相关,包括:清空分页线程变量等。
     * @return
     * @date 2022-11-21
     * @date 2023-01-28 去掉pathPattern限制,因为拦截器里面已经判断,对于特征 '/list' 统一执行分页准备。
     * @date 2023-03-09 重写平台拦截器,添加对报表浏览权限控制。
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry){
//        registry.addInterceptor(new WebOperationInterceptor())
//                .addPathPatterns("/system/**", "/api/**")
        ;
        PlatformOperationInterceptor platformOperationInterceptor = new PlatformOperationInterceptor();
        platformOperationInterceptor.setTokenGenerator(this.tokenGenerator);
        registry.addInterceptor(platformOperationInterceptor);
        logger.info(".......... WebOperationInterceptor 注册成功");
    }
 
//    /**
//     * 配置远程HTTP调用模板。
//     * @return
//     * @date 2023-03-01
//     */
//    @Bean
//    public RestTemplate restTemplate(){
//        RestTemplate restTemplate = new RestTemplate();
//        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
//        Iterator<HttpMessageConverter<?>> iterator=messageConverters.iterator();
//        while(iterator.hasNext()){
//            HttpMessageConverter<?> converter=iterator.next();
//            //原有的String是ISO-8859-1编码 去掉
//            if(converter instanceof StringHttpMessageConverter){
//                iterator.remove();
//            }
//        }
//        messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
//        return restTemplate;
//    }
 
    @Bean
    public RestTemplateProperties restTemplateProperties(){
        return new RestTemplateProperties();
    }
 
    /**
     * 重构 RestTemplate 生成,统一从工厂创建,支持多种http连接池方式,目前仅实现:okhttp
     * @param restTemplateProperties
     * @return
     * @date 2023-08-18
     */
    @Bean
    public RestTemplate restTemplateOkHttp(RestTemplateProperties restTemplateProperties){
        RestTemplateConfig config = new RestTemplateConfig();
        config.setKeepAliveDurationSeconds(restTemplateProperties.getKeepAliveDurationSeconds());
        config.setMaxIdleConnections((int)restTemplateProperties.getMaxIdleConnections());
        config.setConnectTimeoutSeconds(restTemplateProperties.getConnectTimeoutSeconds());
        config.setReadTimeoutSeconds(restTemplateProperties.getReadTimeoutSeconds());
        config.setWriteTimeoutSeconds(restTemplateProperties.getWriteTimeoutSeconds());
        RestTemplate restTemplate = RestTemplateFactory.createRestTemplate(RestTemplateFactory.HttpType.OkHttp, config);
        return restTemplate;
    }
 
    /**
     * 配置一个浏览器代理解析对象。
     * <pre>
     *     1)该对象默认使用基于 BrowserCap 一个开源组件实现底层解析
     *     2)IP查找位置调用了第三方服务: pconline
     * </pre>
     * @return
     * @date 2023-01-05
     */
    @Bean
    public WebAgentService webAgentService(){
        return new BrowserCapWebAgentService();
    }
 
    /**
     * 日志开关配置。
     * @return
     * @date 2023-01-05
     */
    @Bean
    public LogProperties logProperties(){
        return new LogProperties();
    }
 
//    @Bean
//    public PlatformUserCallback testUserCallback(){
//        return new TestUserCallback();
//    }
 
    /**
     * 配置操作日志切面写入对象。
     * @param securitySpi
     * @param logService
     * @return
     * @date 2023-01-06
     */
    @Bean
    public LogAspect logAspect(SecuritySpi securitySpi, LogServiceImpl logService, LogProperties logProperties){
        LogAspect logAspect = new LogAspect();
        logAspect.setSecuritySpi(securitySpi);
        logAspect.setLogService(logService);
        logAspect.setEnableLog(logProperties.isOperateEnabled());
        logger.info("创建:LogAspect...");
        return logAspect;
    }
}