AuthAccessTokenServiceImpl.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. package com.dk.oauth.service.impl;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.baomidou.mybatisplus.core.metadata.IPage;
  4. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  5. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  6. import com.dk.common.infrastructure.constant.Constant;
  7. import com.dk.common.infrastructure.constant.OauthConstants;
  8. import com.dk.common.infrastructure.enums.ErrorCodeEnum;
  9. import com.dk.common.model.response.mst.StaffResponse;
  10. import com.dk.common.response.ResponseCodeEnum;
  11. import com.dk.common.response.ResponseResultUtil;
  12. import com.dk.common.response.ResponseResultVO;
  13. import com.dk.common.util.DateUtils;
  14. import com.dk.common.util.HttpUtils;
  15. import com.dk.oauth.config.WxConfig;
  16. import com.dk.oauth.dto.AuthAccessTokenDto;
  17. import com.dk.oauth.entity.*;
  18. import com.dk.oauth.feign.service.StaffFeign;
  19. import com.dk.oauth.mapper.AuthAccessTokenMapper;
  20. import com.dk.oauth.mapper.CompanyMapper;
  21. import com.dk.oauth.mapper.UserMapper;
  22. import com.dk.oauth.service.IAuthAccessTokenService;
  23. import com.dk.oauth.shiro.jwt.JWTGenerator;
  24. import com.dk.oauth.util.AESSecurityUtil;
  25. import com.dk.oauth.util.UUID;
  26. import lombok.extern.slf4j.Slf4j;
  27. import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
  28. import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
  29. import org.apache.shiro.SecurityUtils;
  30. import org.slf4j.Logger;
  31. import org.slf4j.LoggerFactory;
  32. import org.springframework.beans.factory.annotation.Autowired;
  33. import org.springframework.beans.factory.annotation.Value;
  34. import org.springframework.data.redis.core.StringRedisTemplate;
  35. import org.springframework.stereotype.Service;
  36. import org.springframework.transaction.annotation.Transactional;
  37. import javax.annotation.Resource;
  38. import javax.servlet.http.HttpServletRequest;
  39. import javax.servlet.http.HttpServletResponse;
  40. import java.io.File;
  41. import java.time.LocalDate;
  42. import java.time.LocalDateTime;
  43. import java.util.Date;
  44. import java.util.HashMap;
  45. import java.util.Map;
  46. import java.util.concurrent.TimeUnit;
  47. /**
  48. * (AuthAccessToken)表服务实现类
  49. *
  50. * @author dapeng
  51. * @since 2022-07-01 09:41:05
  52. */
  53. @Slf4j
  54. @Service("authAccessTokenService")
  55. public class AuthAccessTokenServiceImpl extends ServiceImpl<AuthAccessTokenMapper, AuthAccessToken> implements IAuthAccessTokenService {
  56. private final Logger logger = LoggerFactory.getLogger(this.getClass());
  57. @Resource
  58. private AuthAccessTokenMapper authAccessTokenMapper;
  59. @Resource
  60. private UserMapper userMapper;
  61. @Resource
  62. private CompanyMapper companyMapper;
  63. @Value("${aes-key}")
  64. private String AESKey;
  65. @Resource
  66. private StringRedisTemplate stringRedisTemplate;
  67. @Autowired
  68. private WxConfig config;
  69. @Resource
  70. private StaffFeign staffFeign;
  71. /**
  72. * 分页查询
  73. *
  74. * @param
  75. * @return
  76. */
  77. @Override
  78. public ResponseResultVO pageQuery(AuthAccessTokenDto authAccessTokenDto) {
  79. if (null == authAccessTokenDto.getPage()) {
  80. authAccessTokenDto.setPage(new Page(0, 10));
  81. }
  82. IPage<AuthAccessTokenDto> authAccessTokenDtos = authAccessTokenMapper.pageQuery(authAccessTokenDto.getPage(), authAccessTokenDto);
  83. return ResponseResultUtil.success(authAccessTokenDtos);
  84. }
  85. /**
  86. * @desc : 查询用户最新token
  87. * @author : 洪旭东
  88. * @date : 2022-08-02 17:30
  89. */
  90. public String getCurrentToken(Long userId) {
  91. return authAccessTokenMapper.getCurrentToken(userId);
  92. }
  93. /**
  94. * @desc : 登录凭证校验
  95. * @author : 姜永辉
  96. * @date : 2022/5/12 9:33
  97. */
  98. public ResponseResultVO<JSONObject> loginWechat(Map<String, Object> map) {
  99. ResponseResultVO<JSONObject> res = HttpUtils.get(config.getCode2Session()
  100. + "appid=" + config.getAppId()
  101. + "&secret=" + config.getAppSecret()
  102. + "&js_code=" + map.get("code")
  103. + "&grant_type=authorization_code");
  104. if (res.getData() != null && res.getData().get("errcode") != null) {
  105. return ResponseResultUtil.error(ResponseCodeEnum.OPERATE_FAIL.getCode(),
  106. res.getData().get("errmsg") == null ? res.getData().getString("errcode")
  107. : "微信服务器异常:" + res.getData().getString("errmsg"));
  108. }
  109. return res;
  110. }
  111. /**
  112. * @desc : 获取token
  113. * @author : 洪旭东
  114. * @date : 2024-02-20 14:04
  115. */
  116. public ResponseResultVO token(HttpServletRequest request) {
  117. UserLogin userLogin = userMapper.getByPhone(request.getParameter("phone"));
  118. if (userLogin == null || (!userLogin.getUserPwd().equals(request.getParameter("password")))) {
  119. //无用户 或 密码错误
  120. return ResponseResultUtil.error(ErrorCodeEnum.USER_PASSWORD_ERROR.getCode(), ErrorCodeEnum.USER_PASSWORD_ERROR.getMessage());
  121. }
  122. userLogin.checkUserLogin();
  123. try {
  124. // 设置应用代码
  125. userLogin.setAppCode(Constant.AppCode.WEB.getCode());
  126. return createToken(userLogin);
  127. } catch (Exception e) {
  128. log.error("获取accessToken发生异常=", e);
  129. return ResponseResultUtil.error(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
  130. }
  131. }
  132. /**
  133. * @desc : 小程序通过微信openid登录
  134. * @author : 洪旭东
  135. * @date : 2024-02-20 14:04
  136. */
  137. @Transactional(rollbackFor = Exception.class)
  138. public ResponseResultVO wxToken(UserWxLogin userWxLogin) {
  139. // todo
  140. // userWxLogin.setUserWxid("1");
  141. UserLogin userLogin = userMapper.getByWxid(userWxLogin.getUserWxid());
  142. if (userLogin == null) {
  143. //无用户
  144. return ResponseResultUtil.error(ErrorCodeEnum.USER_NOT_EXIST.getCode(), ErrorCodeEnum.USER_NOT_EXIST.getMessage());
  145. }
  146. userLogin.checkUserLogin();
  147. try {
  148. // 设置应用代码
  149. userLogin.setAppCode(Constant.AppCode.WEIXIN.getCode());
  150. return createToken(userLogin);
  151. } catch (Exception e) {
  152. log.error("获取accessToken发生异常=", e);
  153. return ResponseResultUtil.error(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
  154. }
  155. }
  156. /**
  157. * @desc : 小程序通过微信openid登录--体验的账号
  158. * @author : 姜永辉
  159. * @date : 2024-02-20 14:04
  160. */
  161. @Transactional(rollbackFor = Exception.class)
  162. public ResponseResultVO wxFeignExperienceToken(UserWxLogin userWxLogin) {
  163. UserLogin userLogin = userMapper.getByWxid(userWxLogin.getUserWxid());
  164. if (userLogin == null) {
  165. //无用户
  166. return ResponseResultUtil.error(ErrorCodeEnum.USER_NOT_EXIST.getCode(), ErrorCodeEnum.USER_NOT_EXIST.getMessage());
  167. }
  168. try {
  169. // 设置应用代码
  170. userLogin.setAppCode(Constant.AppCode.WEIXIN.getCode());
  171. return createFeignExperienceToken(userLogin);
  172. } catch (Exception e) {
  173. log.error("获取accessToken发生异常=", e);
  174. return ResponseResultUtil.error(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
  175. }
  176. }
  177. /**
  178. * @desc : 登录验证成功,生成token
  179. * @author : 姜永辉
  180. * @date : 2024-02-20 10:31
  181. */
  182. private ResponseResultVO<?> createFeignExperienceToken(UserLogin userLogin) throws OAuthSystemException {
  183. String clientId = "dkic";
  184. AuthAccessToken authAccessToken = new AuthAccessToken();
  185. String username = "";
  186. String userId = "";
  187. username = userLogin.getUserName();
  188. userId = String.valueOf(userLogin.getUserId());
  189. //当前公司
  190. CompanyResponse company = null;
  191. String accessToken = "";
  192. if (userLogin.getCurrentCp() != null) {
  193. company = companyMapper.getByCpId(userLogin.getCurrentCp());
  194. if (company != null) {
  195. JWTGenerator jwtGenerator = new JWTGenerator();
  196. jwtGenerator.setSalt(username);
  197. jwtGenerator.setUsername(username);
  198. jwtGenerator.setUserId(userId);
  199. jwtGenerator.setClientId(clientId);
  200. jwtGenerator.setCpId(company.getCpId().toString());
  201. jwtGenerator.setCpCode(company.getCpCode());
  202. OAuthIssuerImpl oAuthIssuer = new OAuthIssuerImpl(jwtGenerator);
  203. accessToken = oAuthIssuer.accessToken();
  204. log.info("服务器生成的accessToken=" + accessToken);
  205. // 保存token
  206. authAccessToken.setId(UUID.uuid32());
  207. authAccessToken.setClientId(clientId);
  208. authAccessToken.setTokenId(accessToken);
  209. authAccessToken.setCreateDate(new Date());
  210. authAccessToken.setCpId(company.getCpId().toString());
  211. authAccessToken.setCpCode(company.getCpCode());
  212. authAccessToken.setTokenExpiredSeconds(OauthConstants.EXPIRES_IN);
  213. log.info("---->>>SecurityUtils.getSubject().isAuthenticated() = " + SecurityUtils.getSubject().isAuthenticated());
  214. // endregion
  215. // region 加密accessToken
  216. try {
  217. accessToken = AESSecurityUtil.encrypt(AESKey, accessToken);
  218. } catch (Exception e) {
  219. logger.error("sorry,accessToken({}) encode faild!!", accessToken);
  220. }
  221. }
  222. }
  223. // 默认取体验公司的dktest账号
  224. Map<String, Object> collectQuery = new HashMap<>();
  225. collectQuery.put("cpId", userLogin.getCurrentCp());
  226. collectQuery.put("staffCode", "东科智云-标准版-体验");
  227. ResponseResultVO<StaffResponse> feignExperience = staffFeign.getFeignExperience(collectQuery);
  228. StaffResponse s = new StaffResponse();
  229. log.info("---->>>getFeignExperience = " + feignExperience.toString());
  230. //如果没有成功返回,状态设置为待审
  231. if (feignExperience.getCode() != ResponseCodeEnum.SUCCESS.getCode()) {
  232. //无用户
  233. return ResponseResultUtil.error(ErrorCodeEnum.USER_NOT_EXIST.getCode(), ErrorCodeEnum.USER_NOT_EXIST.getMessage());
  234. } else {
  235. s = feignExperience.getData();
  236. }
  237. UserLoginSuccess userLoginSuccess = new UserLoginSuccess()
  238. .setByUserLogin(userLogin)
  239. .setAccessToken(accessToken)
  240. .setCompany(company)
  241. .setStaffResponse(s)
  242. // .setMenuList(userMapper.getMenuByUser(userLogin.getAppCode(),userId,company.getCpId(),"zh_CN"))
  243. ;
  244. return ResponseResultUtil.success(userLoginSuccess);
  245. }
  246. /**
  247. * @desc : 注册
  248. * @author : 洪旭东
  249. * @date : 2024-02-20 13:55
  250. */
  251. @Transactional(rollbackFor = Exception.class)
  252. public ResponseResultVO<?> register(UserWxLogin userWxLogin) {
  253. UserLogin userLogin = userMapper.getByWxid(userWxLogin.getUserWxid());
  254. //通过openid查到用户,但手机号为空
  255. if (userLogin != null && userLogin.getUserPhone() == null) {
  256. //将其他微信用户的相同电话清空
  257. userMapper.cleanPhone(userWxLogin.getUserPhone());
  258. //更新当前手机号
  259. userMapper.updatePhone(userLogin.getUserId(), userWxLogin.getUserPhone());
  260. }
  261. if (userLogin == null) {
  262. //openid没查到,用手机号再查一次
  263. userLogin = userMapper.getByPhone(userWxLogin.getUserPhone());
  264. } else if (userLogin.getUserWxid() == null) {
  265. //通过手机号查到了用户,但是openid是空,更新上当前的openid
  266. userMapper.updateWxid(userLogin.getUserId(), userWxLogin.getUserWxid());
  267. }
  268. //用户无法通过openid或手机号查到 或 通过手机号查到了,但openid不同
  269. if (userLogin == null || !userWxLogin.getUserWxid().equals(userLogin.getUserWxid())) {
  270. //将其他微信用户的相同电话清空
  271. userMapper.cleanPhone(userWxLogin.getUserPhone());
  272. //注册
  273. userMapper.insert(userWxLogin);
  274. userLogin = userMapper.getByWxid(userWxLogin.getUserWxid());
  275. }
  276. userLogin.checkUserLogin();
  277. try {
  278. return createToken(userLogin);
  279. } catch (Exception e) {
  280. log.error("获取accessToken发生异常=", e);
  281. return ResponseResultUtil.error(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
  282. }
  283. }
  284. /**
  285. * @desc : 验证当前扫码登录是否匹配到openid
  286. * @author : 洪旭东
  287. * @date : 2024-02-20 14:04
  288. */
  289. public ResponseResultVO<?> checkLoginOpenId(String uuid) {
  290. String openId = stringRedisTemplate.opsForValue().get(Constant.RedisConstant.REDIS_LOGIN_UUID.getName() + uuid);
  291. if (openId != null && !"".equals(openId)) {
  292. UserLogin userLogin = userMapper.getByWxid(openId);
  293. if (userLogin == null) {
  294. stringRedisTemplate.opsForValue().set(Constant.RedisConstant.REDIS_LOGIN_UUID.getName() + uuid, "", 5, TimeUnit.MINUTES);
  295. //无用户
  296. return ResponseResultUtil.error(ErrorCodeEnum.USER_NOT_EXIST.getCode(), ErrorCodeEnum.USER_NOT_EXIST.getMessage());
  297. }
  298. userLogin.checkUserLogin();
  299. try {
  300. return createToken(userLogin);
  301. } catch (OAuthSystemException e) {
  302. e.printStackTrace();
  303. log.error("获取accessToken发生异常=", e);
  304. return ResponseResultUtil.error(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
  305. }
  306. } else {
  307. return ResponseResultUtil.error(ResponseCodeEnum.NO_LOGIN);
  308. }
  309. }
  310. /**
  311. * @desc : 登录验证成功,生成token
  312. * @author : 洪旭东
  313. * @date : 2024-02-20 10:31
  314. */
  315. private ResponseResultVO<?> createToken(UserLogin userLogin) throws OAuthSystemException {
  316. String clientId = "dkic";
  317. AuthAccessToken authAccessToken = new AuthAccessToken();
  318. // region 开始生成Access Token
  319. String username = "";
  320. String userId = "";
  321. username = userLogin.getUserName();
  322. userId = String.valueOf(userLogin.getUserId());
  323. // endregion
  324. //当前公司
  325. CompanyResponse company = null;
  326. String accessToken = "";
  327. if (userLogin.getCurrentCp() != null) {
  328. company = companyMapper.getByCpId(userLogin.getCurrentCp());
  329. if (company != null) {
  330. JWTGenerator jwtGenerator = new JWTGenerator();
  331. jwtGenerator.setSalt(username);
  332. jwtGenerator.setUsername(username);
  333. jwtGenerator.setUserId(userId);
  334. jwtGenerator.setClientId(clientId);
  335. jwtGenerator.setCpId(company.getCpId().toString());
  336. jwtGenerator.setCpCode(company.getCpCode());
  337. jwtGenerator.setAppCode(userLogin.getAppCode());
  338. OAuthIssuerImpl oAuthIssuer = new OAuthIssuerImpl(jwtGenerator);
  339. accessToken = oAuthIssuer.accessToken();
  340. log.info("服务器生成的accessToken=" + accessToken);
  341. // 保存token
  342. authAccessToken.setId(UUID.uuid32());
  343. authAccessToken.setClientId(clientId);
  344. authAccessToken.setTokenId(accessToken);
  345. authAccessToken.setCreateDate(new Date());
  346. authAccessToken.setUserId(userId);
  347. authAccessToken.setCpId(company.getCpId().toString());
  348. authAccessToken.setCpCode(company.getCpCode());
  349. authAccessToken.setAppCode(userLogin.getAppCode());
  350. authAccessToken.setTokenExpiredSeconds(OauthConstants.EXPIRES_IN);
  351. log.info("---->>>SecurityUtils.getSubject().isAuthenticated() = " + SecurityUtils.getSubject().isAuthenticated());
  352. // endregion
  353. // region 加密accessToken
  354. try {
  355. accessToken = AESSecurityUtil.encrypt(AESKey, accessToken);
  356. // 往redis记录缓存
  357. Map<String,Object> ul = new HashMap<>();
  358. ul.put("accessToken",accessToken);
  359. ul.put("opUpdateTime",LocalDateTime.now());
  360. stringRedisTemplate.opsForValue().set(Constant.RedisConstant.REDIS_USER_LOGIN.getName() + '_' + userId + '_' + userLogin.getAppCode(), JSONObject.toJSONString(ul));
  361. } catch (Exception e) {
  362. logger.error("sorry,accessToken({}) encode faild!!", accessToken);
  363. }
  364. }
  365. }
  366. UserLoginSuccess userLoginSuccess = new UserLoginSuccess()
  367. .setByUserLogin(userLogin)
  368. .setAccessToken(accessToken)
  369. .setCompany(company);
  370. return ResponseResultUtil.success(userLoginSuccess);
  371. }
  372. /**
  373. * @desc : 生成微信临时二维码
  374. * @author : 洪旭东
  375. * @date : 2024-02-20 17:00
  376. */
  377. public ResponseResultVO<?> getQrCode(String uuid) {
  378. //获取access token
  379. String accessToken = stringRedisTemplate.opsForValue().get(Constant.RedisConstant.REDIS_WECHAT_ACCESS_TOKEN.getName());
  380. if (accessToken == null) {
  381. ResponseResultVO<JSONObject> tokenRes = HttpUtils.get(config.getAccessToken() + "appid=" + config.getOffiAccountAppId() + "&secret=" + config.getOffiAccountAppSecret());
  382. if (tokenRes.getCode() == ResponseCodeEnum.SUCCESS.getCode()) {
  383. stringRedisTemplate.opsForValue().set(Constant.RedisConstant.REDIS_WECHAT_ACCESS_TOKEN.getName(), tokenRes.getData().getString("access_token"), 5, TimeUnit.MINUTES);
  384. accessToken = tokenRes.getData().getString("access_token");
  385. } else {
  386. return tokenRes;
  387. }
  388. }
  389. //生成临时二维码
  390. String ticket;
  391. JSONObject json = new JSONObject();
  392. //有效期30天,最大可设置30天
  393. json.put("expire_seconds", 2592000);
  394. json.put("action_name", "QR_STR_SCENE");
  395. JSONObject scene = new JSONObject();
  396. scene.put("scene_str", "dkic-scan-login-" + uuid);
  397. JSONObject actionInfo = new JSONObject();
  398. actionInfo.put("scene", scene);
  399. json.put("action_info", actionInfo);
  400. ResponseResultVO<JSONObject> ticketRes = HttpUtils.post(config.getQrcodeCreate() + accessToken, json);
  401. if (ticketRes.getCode() == ResponseCodeEnum.SUCCESS.getCode()) {
  402. ticket = ticketRes.getData().getString("ticket");
  403. } else {
  404. return ticketRes;
  405. }
  406. stringRedisTemplate.opsForValue().set(Constant.RedisConstant.REDIS_LOGIN_UUID.getName() + uuid, "", 5, TimeUnit.MINUTES);
  407. return ResponseResultUtil.success(config.getShowQrCode() + ticket);
  408. }
  409. /**
  410. * @desc : 生成微信小程序二维码
  411. * @author : 姜永辉
  412. * @date : 2024-02-20 17:00
  413. */
  414. public ResponseResultVO<?> getWxQrCode(Map<String, Object> map) {
  415. System.out.println("getWxQrCode:" + map);
  416. //获取access token
  417. String accessToken = stringRedisTemplate.opsForValue().get(Constant.RedisConstant.REDIS_WECHAT_QRCODE_ACCESS_TOKEN.getName());
  418. if (accessToken == null) {
  419. ResponseResultVO<JSONObject> tokenRes = HttpUtils.get(config.getAccessToken()
  420. + "appid=" + config.getAppId()
  421. + "&secret=" + config.getAppSecret());
  422. if (tokenRes.getCode() == ResponseCodeEnum.SUCCESS.getCode()) {
  423. stringRedisTemplate.opsForValue().set(Constant.RedisConstant.REDIS_WECHAT_QRCODE_ACCESS_TOKEN.getName(),
  424. tokenRes.getData().getString("access_token"), 5, TimeUnit.MINUTES);
  425. accessToken = tokenRes.getData().getString("access_token");
  426. } else {
  427. return tokenRes;
  428. }
  429. }
  430. //二维码参数
  431. Map<String, Object> param = new HashMap<>();
  432. param.put("page", "pages/welcome/welcome");
  433. param.put("scene", "s=" + map.get("openid"));
  434. param.put("check_path", false);
  435. //生成二维码接口地址
  436. String url = config.getUnlimitedQRCode() + accessToken;
  437. //文件名称
  438. String fileName = java.util.UUID.randomUUID().toString() + ".png";
  439. //文件相对路径 - 返回
  440. String relativePath = "/qr_code/" + fileName;
  441. //文件绝对路径 - 写
  442. String absolutelyPath = this.createDirByPath("qr_code") + fileName;
  443. ResponseResultVO<String> responseResultVO = HttpUtils.postReturnFile(url, param, absolutelyPath);
  444. if (responseResultVO.getCode() == ResponseCodeEnum.SUCCESS.getCode()) {
  445. return ResponseResultUtil.success(relativePath);
  446. } else {
  447. return responseResultVO;
  448. }
  449. }
  450. private String createDirByPath(String type) {
  451. /**
  452. * @date_time 2020-07-31 09:42
  453. * @author H_x_d
  454. * @description 根据类型创建目录文件夹
  455. * @param [type]
  456. * @return java.lang.String
  457. */
  458. String path = type + "/" + DateUtils.formatNow("yyyy-MM-dd") + "/";
  459. String base = config.getUploadPath();
  460. File baseDir = new File(base);
  461. if (!baseDir.exists()) {
  462. baseDir.mkdir();
  463. }
  464. String[] paths = path.split("/");
  465. for (int i = 0; i < paths.length; i++) {
  466. base = base + "/" + paths[i];
  467. File dir = new File(base);
  468. if (!dir.exists()) {
  469. dir.mkdir();
  470. }
  471. }
  472. return base + "/";
  473. }
  474. }