尚医通day11-Java中阿里云对象存储OSS

嚴華  金牌会员 | 2023-6-14 11:43:21 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 941|帖子 941|积分 2823

页面预览

用户认证


  • 用户登录成功后都要进行身份认证,认证通过后才可以预约挂号。
  • 认证过程:用户填写基本信息(姓名、证件类型、证件号码和证件照片),提交平台审核
  • 用户认证相关接口:
(1)上传证件图片
(2)提交认证
(3)获取认证信息
提交认证


获取认证信息


第01章-阿里云OSS

1、对象存储OSS

用户认证需要上传证件图片,因此我们要做文件服务,为了解决海量数据存储与弹性扩容,项目中我们采用云存储的解决方案:阿里云OSS。
1.1、开通“对象存储OSS”服务

(1)申请阿里云账号
(2)实名认证
(3)开通“对象存储OSS”服务
(4)进入管理控制台
1.2、创建Bucket

为Bucket起一个名字,其余选项默认即可。
注意:项目中涉及身份证照片,读写权限选择默认的“私有”

得到endpoint:创建Bucket后,在概览页面可以获取当前Bucket的endpoint值,这个值后面编程的时候会用到

1.3、上传测试文件

创建一个文件夹,上传一个文件

2、使用RAM子用户

2.1、进入子用户管理页面



2.2、添加用户


2.3、获取子用户Id和key

AccessKeyId, AccessKeySecret
2.4、设置用户权限

添加权限:AliyunOSSFullAccess

3、使用SDK

在对象存储首页的右侧,可以找到帮助文档的入口


第02章-用户认证

1、新建云服务模块

1.1、创建模块

在service模块下创建子模块service-yun

1.2、添加依赖

在service-yun中引入依赖
  1. <dependencies>
  2.    
  3.     <dependency>
  4.         <groupId>com.aliyun.oss</groupId>
  5.         <artifactId>aliyun-sdk-oss</artifactId>
  6.         <version>3.15.1</version>
  7.     </dependency>
  8.    
  9.     <dependency>
  10.         <groupId>com.atguigu</groupId>
  11.         <artifactId>model</artifactId>
  12.         <version>1.0</version>
  13.     </dependency>
  14.    
  15.     <dependency>
  16.         <groupId>com.atguigu</groupId>
  17.         <artifactId>service-util</artifactId>
  18.         <version>1.0</version>
  19.     </dependency>
  20.    
  21.    
  22.     <dependency>
  23.         <groupId>joda-time</groupId>
  24.         <artifactId>joda-time</artifactId>
  25.     </dependency>
  26.    
  27.    
  28.     <dependency>
  29.         <groupId>com.atguigu</groupId>
  30.         <artifactId>spring-security</artifactId>
  31.         <version>1.0</version>
  32.     </dependency>
  33.    
  34.    
  35.     <dependency>
  36.         <groupId>org.springframework.boot</groupId>
  37.         <artifactId>spring-boot-starter-test</artifactId>
  38.         <scope>test</scope>
  39.     </dependency>
  40. </dependencies>
复制代码
1.3、创建配置文件

在server-yun模块中resources目录下创建文件
application.yml:
  1. spring:
  2.   application:
  3.     name: service-yun
  4.   profiles:
  5.     active: dev,redis
复制代码
application-dev.yml:
  1. server:
  2.   port: 8204
  3. spring:
  4.   cloud:
  5.     nacos:
  6.       discovery:
  7.         server-addr: 127.0.0.1:8848
  8.   servlet:
  9.     multipart:
  10.       max-file-size: 10MB
  11.       max-request-size: 10MB
  12. logging:
  13.   level:
  14.     root: info
  15.   file:
  16.     path: yun
  17.   
  18. aliyun:
  19.   oss: #阿里云 OSS
  20.     endpoint: your endpoint
  21.     key-id: your accessKeyId
  22.     key-secret: your accessKeySecret
  23.     bucket-name: your bucketname
复制代码
1.4、创建启动类

创建ServiceYunApplication
  1. package com.atguigu.syt.yun;
  2. @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//取消数据源配置自动读取
  3. @ComponentScan(basePackages = {"com.atguigu"})
  4. public class ServiceYunApplication {
  5.     public static void main(String[] args) {
  6.         SpringApplication.run(ServiceYunApplication.class, args);
  7.     }
  8. }
复制代码
1.5、配置网关

在网关中配置如下内容:
  1.         - id: service-yun
  2.           predicates: Path=/*/yun/**
  3.           uri: lb://service-yun
复制代码
2、文件上传

2.1、从配置文件读取常量

创建常量读取工具类:OssConstantProperties.java
  1. package com.atguigu.syt.yun.utils;
  2. @Configuration
  3. @ConfigurationProperties(prefix="aliyun.oss") //读取节点
  4. @Data
  5. public class OssConstantProperties {
  6.    
  7.     private String endpoint;
  8.     private String keyId;
  9.     private String keySecret;
  10.     private String bucketName;
  11. }
复制代码
2.2、Controller

创建controller.front包,创建FrontFileController类
  1. package com.atguigu.syt.yun.controller.front;
  2. @Api(tags = "阿里云文件管理")
  3. @RestController
  4. @RequestMapping("/front/yun/file")
  5. public class FrontFileController {
  6.     @Resource
  7.     private FileService fileService;
  8.     /**
  9.      * 文件上传
  10.      */
  11.     @ApiOperation("文件上传")
  12.     @ApiImplicitParam(name = "file",value = "上传文件", required = true)
  13.     @PostMapping("/auth/upload")
  14.     public Result<Map<String, String>> upload(MultipartFile file) {
  15.         Map<String, String> map = fileService.upload(file);
  16.         return Result.ok(map);
  17.     }
  18. }
复制代码
2.3、Service

接口:FileService
  1. package com.atguigu.syt.oss.service;
  2. public interface FileService {
  3.     /**
  4.      * 文件上传
  5.      * @param file
  6.      * @return
  7.      */
  8.     Map<String, String> upload(MultipartFile file);
  9. }
复制代码
实现:FileServiceImpl
参考SDK中的:Java->上传文件->简单上传->流式上传->上传文件流
  1. package com.atguigu.syt.oss.service.impl;
  2. @Service
  3. @Slf4j
  4. public class FileServiceImpl implements FileService {
  5.     @Resource
  6.     private OssConstantProperties ossConstantProperties;
  7.     /**
  8.      * 参考SDK中的:Java->上传文件->简单上传->流式上传->上传文件流
  9.      * @param file
  10.      * @return
  11.      */
  12.     @Override
  13.     public Map<String, String> upload(MultipartFile file) {
  14.         // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
  15.         String endpoint = ossConstantProperties.getEndpoint();
  16.         // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
  17.         String accessKeyId = ossConstantProperties.getKeyId();
  18.         String accessKeySecret = ossConstantProperties.getKeySecret();
  19.         // 填写Bucket名称,例如examplebucket。
  20.         String bucketName = ossConstantProperties.getBucketName();
  21.         // 文件名称
  22.         String originalFilename = file.getOriginalFilename();
  23.         String dateString = new DateTime().toString("yyyyMMdd");
  24.         // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
  25.         String objectName =
  26.                 dateString
  27.                         + "/" + UUID.randomUUID().toString().replace("-", "")
  28.                         + originalFilename.substring(originalFilename.lastIndexOf("."));
  29.         // 创建OSSClient实例。
  30.         OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
  31.         try {
  32.             InputStream inputStream = file.getInputStream();
  33.             // 创建PutObjectRequest对象。
  34.             PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
  35.             // 设置该属性可以返回response。如果不设置,则返回的response为空。
  36.             putObjectRequest.setProcess("true");
  37.             // 创建PutObject请求。
  38.             PutObjectResult result = ossClient.putObject(putObjectRequest);
  39.             // 如果上传成功,则返回200。
  40.             log.info(Integer.toString(result.getResponse().getStatusCode()));
  41.             if(result.getResponse().getStatusCode() != 200){
  42.                 throw new GuiguException(ResultCodeEnum.FAIL);
  43.             }
  44.             //返回图片路径
  45.             //参考SDK中的:Java-> Java授权访问-> 生成以GET方法访问的签名URL
  46.             // 设置URL过期时间为1小时,单位:毫秒
  47.             Date expiration = new Date(new Date().getTime() + 60 * 60 * 1000);
  48.             URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
  49.             Map<String, String> map = new HashMap<>();
  50.             map.put("previewUrl", url.toString()); //页面中授权预览图片
  51.             map.put("url", objectName); //数据库存储
  52.             return map;
  53.         } catch (OSSException oe) {
  54.             System.out.println("Caught an OSSException, which means your request made it to OSS, "
  55.                     + "but was rejected with an error response for some reason.");
  56.             System.out.println("Error Message:" + oe.getErrorMessage());
  57.             System.out.println("Error Code:" + oe.getErrorCode());
  58.             System.out.println("Request ID:" + oe.getRequestId());
  59.             System.out.println("Host ID:" + oe.getHostId());
  60.             throw new GuiguException(ResultCodeEnum.FAIL, oe);
  61.         } catch (GuiguException ce) {
  62.             System.out.println("Caught an ClientException, which means the client encountered "
  63.                     + "a serious internal problem while trying to communicate with OSS, "
  64.                     + "such as not being able to access the network.");
  65.             System.out.println("Error Message:" + ce.getMessage());
  66.             throw new GuiguException(ResultCodeEnum.FAIL, ce);
  67.         } catch (IOException e) {
  68.             throw new GuiguException(ResultCodeEnum.FAIL, e);
  69.         } finally {
  70.             if (ossClient != null) {
  71.                 ossClient.shutdown();
  72.             }
  73.         }
  74.     }
  75. }
复制代码
3、授权校验

3.1、辅助类

在service-util模块中添加AuthContextHolder.java
  1. package com.atguigu.common.service.utils;
  2. /**
  3. * 授权校验
  4. */
  5. @Component
  6. public class AuthContextHolder {
  7.     @Resource
  8.     private RedisTemplate redisTemplate;
  9.     /**
  10.      * 校验token是否存在并返回UserId
  11.      * @param request
  12.      */
  13.     public Long checkAuth(HttpServletRequest request){
  14.         //从http请求头中获取token
  15.         String token = request.getHeader("token");
  16.         if(StringUtils.isEmpty(token)) {
  17.             throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
  18.         }
  19.         Object userIdObj = redisTemplate.opsForValue().get("user:token:" + token);
  20.         //数据存入redis时,按照实际的大小分配空间,取出时int能存下,默认使用int类型,int存不下再用long
  21.         //我们无法判断redis中存储的是什么类型的id,因此在此做一个转换
  22.         Long userId = null;
  23.         if(userIdObj instanceof Integer){
  24.             userId = ((Integer)userIdObj).longValue();
  25.         }else if(userIdObj instanceof Long){
  26.             userId = (Long)userIdObj;
  27.         }else if(userIdObj instanceof String){
  28.             userId = Long.parseLong(userIdObj.toString());
  29.         }
  30.         if(StringUtils.isEmpty(userId)) {
  31.             throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
  32.         }
  33.         return userId;
  34.     }
  35. }
复制代码
3.2、修改文件上传controller

添加校验代码
  1. ...
  2. public class FrontFileController {
  3.     ...
  4.     @Resource
  5.     private AuthContextHolder authContextHolder;
  6.    
  7.     ...
  8.     public Result<Map<String, String>> upload(MultipartFile file, HttpServletRequest request) {
  9.         authContextHolder.checkAuth(request);
  10.         ...
  11.     }
  12. }
复制代码
3.3、测试文件上传

首先添加全局参数token,然后再进行测试

4、提交认证

4.1、Controller

创建FrontUserInfoController中添加如下方法
  1. package com.atguigu.syt.user.controller.front;
  2. @Api(tags = "用户管理")
  3. @RestController
  4. @RequestMapping("/front/user/userInfo")
  5. public class FrontUserInfoController {
  6.     @Resource
  7.     private UserInfoService userInfoService;
  8.     @Resource
  9.     private AuthContextHolder authContextHolder;
  10.     @ApiOperation(value = "用户认证")
  11.     @ApiImplicitParam(name = "userAuthVo",value = "用户实名认证对象", required = true)
  12.     @PostMapping("/auth/userAuth")
  13.     public Result userAuth(@RequestBody UserAuthVo userAuthVo, HttpServletRequest request) {
  14.         Long userId = authContextHolder.checkAuth(request);
  15.         userInfoService.userAuth(userId, userAuthVo);
  16.         return Result.ok();
  17.     }
  18. }
复制代码
4.2、Service

接口:UserInfoService
  1. /**
  2.      * 保存实名认证信息
  3.      * @param userId
  4.      * @param userAuthVo
  5.      */
  6. void userAuth(Long userId, UserAuthVo userAuthVo);
复制代码
实现:UserInfoServiceImpl
  1. @Override
  2. public void userAuth(Long userId, UserAuthVo userAuthVo) {
  3.     //设置认证信息
  4.     UserInfo userInfo = new UserInfo();
  5.     userInfo.setId(userId);
  6.     userInfo.setName(userAuthVo.getName());
  7.     userInfo.setCertificatesType(userAuthVo.getCertificatesType());
  8.     userInfo.setCertificatesNo(userAuthVo.getCertificatesNo());
  9.     userInfo.setCertificatesUrl(userAuthVo.getCertificatesUrl());
  10.     userInfo.setAuthStatus(AuthStatusEnum.AUTH_RUN.getStatus());
  11.     //信息更新
  12.     baseMapper.updateById(userInfo);
  13. }
复制代码
5、获取认证信息

5.1、Controller

在service-user模块的FrontUserInfoController中添加如下方法
  1. @ApiOperation(value = "获取认证信息")
  2. @GetMapping("/auth/getUserInfo")
  3. public Result<UserInfo> getUserInfo(HttpServletRequest request) {
  4.     Long userId = authContextHolder.checkAuth(request);
  5.     UserInfo userInfo = userInfoService.getUserInfoById(userId);
  6.     return Result.ok(userInfo);
  7. }
复制代码
5.2、Service

主类添加
  1. @EnableFeignClients("com.atguigu.syt")
复制代码
接口:UserInfoService
  1. /**
  2.      * 根据用户id获取用户信息
  3.      * @param userId
  4.      * @return
  5.      */
  6. UserInfo getUserInfoById(Long userId);
复制代码
实现:UserInfoServiceImpl
  1. @Override
  2. public UserInfo getUserInfoById(Long userId) {
  3.     UserInfo userInfo = baseMapper.selectById(userId);
  4.     return this.packUserInfo(userInfo);
  5. }
复制代码
辅助方法:UserInfoServiceImpl
  1. @Resource
  2. private DictFeignClient dictFeignClient;
  3. /**
  4.      * 封装用户状态、认证状态、证件类型信息
  5.      * @param userInfo
  6.      * @return
  7.      */
  8. private UserInfo packUserInfo(UserInfo userInfo) {
  9.     String certificatesTypeString = dictFeignClient.getName(
  10.         DictTypeEnum.CERTIFICATES_TYPE.getDictTypeId(),
  11.         userInfo.getCertificatesType()
  12.     );
  13.     userInfo.getParam().put("certificatesTypeString", certificatesTypeString);
  14.     userInfo.getParam().put(
  15.         "authStatusString", AuthStatusEnum.getStatusNameByStatus(userInfo.getAuthStatus())
  16.     );
  17.     userInfo.getParam().put(
  18.         "statusString", UserStatusEnum.getStatusNameByStatus(userInfo.getStatus())
  19.     );
  20.     return userInfo;
  21. }
复制代码
6、显示图片

6.1、Controller

InnerFileController类
  1. package com.atguigu.syt.yun.controller.inner;
  2. @Api(tags = "阿里云文件管理")
  3. @RestController
  4. @RequestMapping("/inner/yun/file")
  5. public class InnerFileController {
  6.     @Resource
  7.     private FileService fileService;
  8.    
  9.     @ApiOperation(value = "获取图片预览Url")
  10.     @ApiImplicitParam(name = "objectName",value = "文件名", required = true)
  11.     @GetMapping("/getPreviewUrl")
  12.     public String getPreviewUrl(@RequestParam String objectName) {
  13.         return fileService.getPreviewUrl(objectName);
  14.     }
  15. }
复制代码
6.2、Service

接口:FileService
  1. /**
  2.      * 获取图片url地址
  3.      * @param objectName
  4.      * @return
  5.      */
  6. String getPreviewUrl(String objectName);
复制代码
实现:FileServiceImpl
  1. @Override
  2. public String getPreviewUrl(String objectName) {
  3.     // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
  4.     String endpoint = ossConstantProperties.getEndpoint();
  5.     // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
  6.     String accessKeyId = ossConstantProperties.getKeyId();
  7.     String accessKeySecret = ossConstantProperties.getKeySecret();
  8.     // 填写Bucket名称,例如examplebucket。
  9.     String bucketName = ossConstantProperties.getBucketName();
  10.     OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
  11.     // 设置URL过期时间为1小时,单位:毫秒
  12.     Date expiration = new Date(new Date().getTime() + 60 * 60 * 1000);
  13.     URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
  14.     System.out.println(url.toString());
  15.     return url.toString();
  16. }
复制代码
6.3、创建service-yun-client


6.4、定义FeignClient

接口:
  1. package com.atguigu.syt.yun.client;
  2. @FeignClient(
  3.         value = "service-yun",
  4.         contextId = "fileFeignClient",
  5.         fallback = FileDegradeFeignClient.class
  6. )
  7. public interface FileFeignClient {
  8.     @GetMapping("inner/yun/file/getPreviewUrl")
  9.     String getPreviewUrl(@RequestParam String objectName);
  10. }
复制代码
降级:
  1. package com.atguigu.syt.yun.client.impl;
  2. @Component
  3. public class FileDegradeFeignClient implements FileFeignClient {
  4.     @Override
  5.     public String getPreviewUrl(String objectName) {
  6.         return "图片显示失败";
  7.     }
  8. }
复制代码
6.5、service中添加依赖
  1. <dependency>
  2.     <groupId>com.atguigu</groupId>
  3.     <artifactId>service-yun-client</artifactId>
  4.     <version>1.0</version>
  5. </dependency>
复制代码
6.6、远程调用

UserInfoServiceImpl:
  1. @Resource
  2. private FileFeignClient fileFeignClient;
复制代码
UserInfoServiceImpl:packUserInfo方法中添加如下代码
  1. String previewUrl = fileFeignClient.getPreviewUrl(userInfo.getCertificatesUrl());
  2. userInfo.getParam().put("previewUrl", previewUrl);
复制代码
注意:由于是远程调用阿里云服务器,因此配置文件中feignClient的远程超时时间可以设置的稍微长一些,避免个别情况下由于网络原因出现的图片无法加载的情况
7、用户认证前端

7.1、api

创建api/userInfo.js
  1. import request from '@/utils/request'
  2. //引入js-cookie
  3. import cookie from 'js-cookie'
  4. export default {
  5.   saveUserAuth(userAuth) {
  6.     return request({
  7.       url: `/front/user/userInfo/auth/userAuth`,
  8.       method: 'post',
  9.       data: userAuth,
  10.       headers:{token: cookie.get('token')}
  11.     })
  12.   },
  13.   getUserInfo() {
  14.     return request({
  15.       url: `/front/user/userInfo/auth/getUserInfo`,
  16.       method: `get`,
  17.       headers:{token: cookie.get('token')}
  18.     })
  19.   }
  20. }
复制代码
7.2、页面渲染

pages/user/index.vue文件
资料:资料>实名认证>user
7.3、统一发送请求头

也可以统一发送请求头:删除api/user.js 中对请求头的设置,修改utils/request.js文件如下
  1. //引入js-cookie
  2. import cookie from 'js-cookie'
复制代码
修改请求拦截器
  1. // http request 拦截器
  2. service.interceptors.request.use(
  3.         config => {
  4.                 //从cookie中取出token,并且在请求头中携带token
  5.                 if (cookie.get('token')) {
  6.                         config.headers['token'] = cookie.get('token')
  7.                 }
  8.                 return config
  9.         },
  10.         err => {
  11.                 return Promise.reject(err)
  12.         })
复制代码
源码:https://gitee.com/dengyaojava/guigu-syt-parent

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

嚴華

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表