页面预览

用户认证

  • 用户登录成功后都要进行身份认证,认证通过后才可以预约挂号。

  • 认证过程:用户填写基本信息(姓名、证件类型、证件号码和证件照片),提交平台审核

  • 用户认证相关接口:

(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中引入依赖

<dependencies>
<!-- 阿里云oss依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency> <!--实体-->
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>model</artifactId>
<version>1.0</version>
</dependency> <!--服务通用配置-->
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-util</artifactId>
<version>1.0</version>
</dependency> <!--时间日期工具-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency> <!--自定义安全模块-->
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>spring-security</artifactId>
<version>1.0</version>
</dependency> <!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependencies>

1.3、创建配置文件

在server-yun模块中resources目录下创建文件

application.yml

spring:
application:
name: service-yun
profiles:
active: dev,redis

application-dev.yml

server:
port: 8204
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB logging:
level:
root: info
file:
path: yun aliyun:
oss: #阿里云 OSS
endpoint: your endpoint
key-id: your accessKeyId
key-secret: your accessKeySecret
bucket-name: your bucketname

1.4、创建启动类

创建ServiceYunApplication

package com.atguigu.syt.yun;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//取消数据源配置自动读取
@ComponentScan(basePackages = {"com.atguigu"})
public class ServiceYunApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceYunApplication.class, args);
}
}

1.5、配置网关

在网关中配置如下内容:

        - id: service-yun
predicates: Path=/*/yun/**
uri: lb://service-yun

2、文件上传

2.1、从配置文件读取常量

创建常量读取工具类:OssConstantProperties.java

package com.atguigu.syt.yun.utils;
@Configuration
@ConfigurationProperties(prefix="aliyun.oss") //读取节点
@Data
public class OssConstantProperties { private String endpoint;
private String keyId;
private String keySecret;
private String bucketName;
}

2.2、Controller

创建controller.front包,创建FrontFileController类

package com.atguigu.syt.yun.controller.front;

@Api(tags = "阿里云文件管理")
@RestController
@RequestMapping("/front/yun/file")
public class FrontFileController { @Resource
private FileService fileService;
/**
* 文件上传
*/
@ApiOperation("文件上传")
@ApiImplicitParam(name = "file",value = "上传文件", required = true)
@PostMapping("/auth/upload")
public Result<Map<String, String>> upload(MultipartFile file) {
Map<String, String> map = fileService.upload(file);
return Result.ok(map);
}
}

2.3、Service

接口:FileService

package com.atguigu.syt.oss.service;

public interface FileService {

    /**
* 文件上传
* @param file
* @return
*/
Map<String, String> upload(MultipartFile file);
}

实现:FileServiceImpl

参考SDK中的:Java->上传文件->简单上传->流式上传->上传文件流

package com.atguigu.syt.oss.service.impl;

@Service
@Slf4j
public class FileServiceImpl implements FileService { @Resource
private OssConstantProperties ossConstantProperties; /**
* 参考SDK中的:Java->上传文件->简单上传->流式上传->上传文件流
* @param file
* @return
*/
@Override
public Map<String, String> upload(MultipartFile file) { // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = ossConstantProperties.getEndpoint();
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = ossConstantProperties.getKeyId();
String accessKeySecret = ossConstantProperties.getKeySecret();
// 填写Bucket名称,例如examplebucket。
String bucketName = ossConstantProperties.getBucketName(); // 文件名称
String originalFilename = file.getOriginalFilename();
String dateString = new DateTime().toString("yyyyMMdd");
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName =
dateString
+ "/" + UUID.randomUUID().toString().replace("-", "")
+ originalFilename.substring(originalFilename.lastIndexOf(".")); // 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); try {
InputStream inputStream = file.getInputStream();
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 设置该属性可以返回response。如果不设置,则返回的response为空。
putObjectRequest.setProcess("true");
// 创建PutObject请求。
PutObjectResult result = ossClient.putObject(putObjectRequest); // 如果上传成功,则返回200。
log.info(Integer.toString(result.getResponse().getStatusCode()));
if(result.getResponse().getStatusCode() != 200){
throw new GuiguException(ResultCodeEnum.FAIL);
} //返回图片路径
//参考SDK中的:Java-> Java授权访问-> 生成以GET方法访问的签名URL
// 设置URL过期时间为1小时,单位:毫秒
Date expiration = new Date(new Date().getTime() + 60 * 60 * 1000);
URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration); Map<String, String> map = new HashMap<>();
map.put("previewUrl", url.toString()); //页面中授权预览图片
map.put("url", objectName); //数据库存储 return map; } catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId()); throw new GuiguException(ResultCodeEnum.FAIL, oe); } catch (GuiguException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage()); throw new GuiguException(ResultCodeEnum.FAIL, ce); } catch (IOException e) { throw new GuiguException(ResultCodeEnum.FAIL, e); } finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}

3、授权校验

3.1、辅助类

在service-util模块中添加AuthContextHolder.java

package com.atguigu.common.service.utils;

/**
* 授权校验
*/
@Component
public class AuthContextHolder { @Resource
private RedisTemplate redisTemplate; /**
* 校验token是否存在并返回UserId
* @param request
*/
public Long checkAuth(HttpServletRequest request){
//从http请求头中获取token
String token = request.getHeader("token");
if(StringUtils.isEmpty(token)) {
throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
} Object userIdObj = redisTemplate.opsForValue().get("user:token:" + token); //数据存入redis时,按照实际的大小分配空间,取出时int能存下,默认使用int类型,int存不下再用long
//我们无法判断redis中存储的是什么类型的id,因此在此做一个转换
Long userId = null;
if(userIdObj instanceof Integer){
userId = ((Integer)userIdObj).longValue();
}else if(userIdObj instanceof Long){
userId = (Long)userIdObj;
}else if(userIdObj instanceof String){
userId = Long.parseLong(userIdObj.toString());
} if(StringUtils.isEmpty(userId)) {
throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
} return userId;
}
}

3.2、修改文件上传controller

添加校验代码

...
public class FrontFileController { ...
@Resource
private AuthContextHolder authContextHolder; ...
public Result<Map<String, String>> upload(MultipartFile file, HttpServletRequest request) { authContextHolder.checkAuth(request);
...
}
}

3.3、测试文件上传

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

4、提交认证

4.1、Controller

创建FrontUserInfoController中添加如下方法

package com.atguigu.syt.user.controller.front;

@Api(tags = "用户管理")
@RestController
@RequestMapping("/front/user/userInfo")
public class FrontUserInfoController { @Resource
private UserInfoService userInfoService; @Resource
private AuthContextHolder authContextHolder; @ApiOperation(value = "用户认证")
@ApiImplicitParam(name = "userAuthVo",value = "用户实名认证对象", required = true)
@PostMapping("/auth/userAuth")
public Result userAuth(@RequestBody UserAuthVo userAuthVo, HttpServletRequest request) { Long userId = authContextHolder.checkAuth(request);
userInfoService.userAuth(userId, userAuthVo);
return Result.ok();
}
}

4.2、Service

接口:UserInfoService

/**
* 保存实名认证信息
* @param userId
* @param userAuthVo
*/
void userAuth(Long userId, UserAuthVo userAuthVo);

实现:UserInfoServiceImpl

@Override
public void userAuth(Long userId, UserAuthVo userAuthVo) {
//设置认证信息
UserInfo userInfo = new UserInfo();
userInfo.setId(userId);
userInfo.setName(userAuthVo.getName());
userInfo.setCertificatesType(userAuthVo.getCertificatesType());
userInfo.setCertificatesNo(userAuthVo.getCertificatesNo());
userInfo.setCertificatesUrl(userAuthVo.getCertificatesUrl());
userInfo.setAuthStatus(AuthStatusEnum.AUTH_RUN.getStatus());
//信息更新
baseMapper.updateById(userInfo);
}

5、获取认证信息

5.1、Controller

在service-user模块的FrontUserInfoController中添加如下方法

@ApiOperation(value = "获取认证信息")
@GetMapping("/auth/getUserInfo")
public Result<UserInfo> getUserInfo(HttpServletRequest request) { Long userId = authContextHolder.checkAuth(request);
UserInfo userInfo = userInfoService.getUserInfoById(userId);
return Result.ok(userInfo);
}

5.2、Service

主类添加

@EnableFeignClients("com.atguigu.syt")

接口:UserInfoService

/**
* 根据用户id获取用户信息
* @param userId
* @return
*/
UserInfo getUserInfoById(Long userId);

实现:UserInfoServiceImpl

@Override
public UserInfo getUserInfoById(Long userId) {
UserInfo userInfo = baseMapper.selectById(userId);
return this.packUserInfo(userInfo);
}

辅助方法:UserInfoServiceImpl

@Resource
private DictFeignClient dictFeignClient; /**
* 封装用户状态、认证状态、证件类型信息
* @param userInfo
* @return
*/
private UserInfo packUserInfo(UserInfo userInfo) {
String certificatesTypeString = dictFeignClient.getName(
DictTypeEnum.CERTIFICATES_TYPE.getDictTypeId(),
userInfo.getCertificatesType()
); userInfo.getParam().put("certificatesTypeString", certificatesTypeString);
userInfo.getParam().put(
"authStatusString", AuthStatusEnum.getStatusNameByStatus(userInfo.getAuthStatus())
);
userInfo.getParam().put(
"statusString", UserStatusEnum.getStatusNameByStatus(userInfo.getStatus())
);
return userInfo;
}

6、显示图片

6.1、Controller

InnerFileController类

package com.atguigu.syt.yun.controller.inner;

@Api(tags = "阿里云文件管理")
@RestController
@RequestMapping("/inner/yun/file")
public class InnerFileController { @Resource
private FileService fileService; @ApiOperation(value = "获取图片预览Url")
@ApiImplicitParam(name = "objectName",value = "文件名", required = true)
@GetMapping("/getPreviewUrl")
public String getPreviewUrl(@RequestParam String objectName) { return fileService.getPreviewUrl(objectName);
}
}

6.2、Service

接口:FileService

/**
* 获取图片url地址
* @param objectName
* @return
*/
String getPreviewUrl(String objectName);

实现:FileServiceImpl

@Override
public String getPreviewUrl(String objectName) {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = ossConstantProperties.getEndpoint();
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = ossConstantProperties.getKeyId();
String accessKeySecret = ossConstantProperties.getKeySecret();
// 填写Bucket名称,例如examplebucket。
String bucketName = ossConstantProperties.getBucketName(); OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 设置URL过期时间为1小时,单位:毫秒
Date expiration = new Date(new Date().getTime() + 60 * 60 * 1000);
URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
System.out.println(url.toString());
return url.toString();
}

6.3、创建service-yun-client

6.4、定义FeignClient

接口:

package com.atguigu.syt.yun.client;
@FeignClient(
value = "service-yun",
contextId = "fileFeignClient",
fallback = FileDegradeFeignClient.class
)
public interface FileFeignClient { @GetMapping("inner/yun/file/getPreviewUrl")
String getPreviewUrl(@RequestParam String objectName);
}

降级:

package com.atguigu.syt.yun.client.impl;

@Component
public class FileDegradeFeignClient implements FileFeignClient {
@Override
public String getPreviewUrl(String objectName) {
return "图片显示失败";
}
}

6.5、service中添加依赖

<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-yun-client</artifactId>
<version>1.0</version>
</dependency>

6.6、远程调用

UserInfoServiceImpl:

@Resource
private FileFeignClient fileFeignClient;

UserInfoServiceImpl:packUserInfo方法中添加如下代码

String previewUrl = fileFeignClient.getPreviewUrl(userInfo.getCertificatesUrl());
userInfo.getParam().put("previewUrl", previewUrl);

注意:由于是远程调用阿里云服务器,因此配置文件中feignClient的远程超时时间可以设置的稍微长一些,避免个别情况下由于网络原因出现的图片无法加载的情况

7、用户认证前端

7.1、api

创建api/userInfo.js

import request from '@/utils/request'

//引入js-cookie
import cookie from 'js-cookie' export default { saveUserAuth(userAuth) {
return request({
url: `/front/user/userInfo/auth/userAuth`,
method: 'post',
data: userAuth,
headers:{token: cookie.get('token')}
})
}, getUserInfo() {
return request({
url: `/front/user/userInfo/auth/getUserInfo`,
method: `get`,
headers:{token: cookie.get('token')}
})
}
}

7.2、页面渲染

pages/user/index.vue文件

资料:资料>实名认证>user

7.3、统一发送请求头

也可以统一发送请求头:删除api/user.js 中对请求头的设置,修改utils/request.js文件如下

//引入js-cookie
import cookie from 'js-cookie'

修改请求拦截器

// http request 拦截器
service.interceptors.request.use(
config => {
//从cookie中取出token,并且在请求头中携带token
if (cookie.get('token')) {
config.headers['token'] = cookie.get('token')
}
return config
},
err => {
return Promise.reject(err)
})

源码:https://gitee.com/dengyaojava/guigu-syt-parent

尚医通day11-Java中阿里云对象存储OSS的更多相关文章

  1. 阿里云对象存储OSS与文件存储NAS的区别

    一.简介 应用场景:选择一款存储产品,面向文档数据的存取,不会涉及到数据处理. 产品选型主要从OSS和NAS中选择一款,满足文档存储的需求. 二.NAS优缺点 NAS 是一种采用直接与网络介质相连的特 ...

  2. 阿里云对象存储OSS访问控制

    阿里云对象存储OSS的Android SDK提供了STS鉴权模式和自签名模式来保障移动终端的安全性. OSS可以通过阿里云STS (Security Token Service) 进行临时授权访问.交 ...

  3. 阿里云对象存储OSS

    阿里云的产品种类繁多,今天让我们一起来了解下对象存储(Object Storage Service,简称OSS)吧! 什么是对象存储呢? 简单来说,对象存储OSS是阿里云提供的海量.安全和高可靠的云存 ...

  4. 阿里云对象存储OSS支持版本管理特性

    阿里云对象存储OSS现已经全面支持“对象版本管理”特性.该功能适用于所有的存储类型以及区域.当Bucket启用该特性后,“对象版本管理”功能可以保护和恢复误删除.误覆盖的数据. 对象存储OSS“版本管 ...

  5. 阿里云对象存储OSS及CDN加速配置

    目录 十大云存储服务商 1. 登陆阿里云官网,开通对象存储服务 OSS 2. 创建存储空间 3. 绑定自定义域名 4. 配置阿里云CDN加速 5. 购买阿里云免费SSL证书 6. 阿里云CDN配置HT ...

  6. 阿里云对象存储OSS使用 HTTPS

    一.前言 阿里云对象存储oss本身也是可以用HTTPS直接访问的,但是它本身的地址是http://***.oss-cn-hangzhou.aliyuncs.com这样的,那么如果我们想使用自己的域名, ...

  7. Delphi阿里云对象存储OSS【支持上传文件、下载文件、删除文件、创建目录、删除目录、Bucket操作等】

    作者QQ:(648437169) 点击下载➨Delphi阿里云对象存储OSS             阿里云api文档 [Delphi阿里云对象存储OSS]支持 获取Bucket列表.设置Bucket ...

  8. java开发之阿里云对象存储OSS和云数据库Memcache的使用

    web开发中标配:aliyun ECS(阿里云服务器),aliyun RDS(阿里云数据库),aliyun OSS(阿里云对象存储),aliyun Memcache(阿里云缓存数据库). 今天就介绍下 ...

  9. 阿里云对象存储 OSS 应用服务器搭建代码

    背景说明 最近做一个APP客户端图片直传阿里云OSS的服务,需要在后台开一个阿里云的OSSToken获取的接口. 阿里云官方文档地址:快速搭建移动应用直传服务. 略过移动端说明,直接看服务端的. 不是 ...

  10. 阿里云对象存储OSS————跨域资源共享(CORS)(m3u8 无法加载m3u8:跨域访问被拒绝)

    今天在做视频直播录像的时候,添加一个录制APP的.M3U8文件到OSS的一个test文件中存储,结果是访问不到了: 提示:无法加载m3u8:跨域访问被拒绝!!!!! 项目代码测试地址:https:// ...

随机推荐

  1. 解决ubuntu 20.04、22.04 即新版本 fcitx 无法使用的问题

    前提 已在系统设置中将fcitx设置为默认 fcitx开机自启 配置的过程不在本文讨论范围之内 开机自启可通过安装gnome-tweaks配置实现 问题分析流程 手动启动fcitx时提示设置XMODI ...

  2. 一文总结你需要的OpenCV操作

    目录 一.OpenCV简介 1.1 OpenCV是什么 1.2 安装及使用 二.图像的基础 2.1 成像原理 2.2 图像格式 2.3 颜色空间 三.OpenCV基础操作 3.1 图像的读取.显示.保 ...

  3. 自己动手从零写桌面操作系统GrapeOS系列教程——1.2 GrapeOS真机演示

    学习操作系统原理最好的方法是自己写一个简单的操作系统. GrapeOS操作系统之前一直运行在模拟器和虚拟机中,今天我们来演示一下GrapeOS在真机上运行的情况. 一.物理机真机 今天演示用的真机是一 ...

  4. 快速部署Ceph分布式高可用集群

    快速部署Ceph分布式高可用集群 Ceph简介 Ceph是一个PB,EB级别的分布式存储系统,可以提供文件存储,对象存储.和块存储,它可靠性高,易扩展,管理简便,其中对象存储和块存储可以和其他云平台集 ...

  5. 随机模块random os模块 序列化模块

    random: 验证码的实现: choice是选择列表中任意一个 ##记得把randint取出来的数字转化成str类型,要不就会相加 ##cha()是把asc编码表里的数字转化成字符 更进一步做成函数 ...

  6. 为什么C++语言性能优越?

    面试时被问到这个问题,发现自己一直以来理所当然的认为C++快,却没有具体分析原因.下面简单总结一下为什么快. 当我们编写程序时,我们需要将程序转换为计算机可以理解的机器语言.不同的语言有不同的执行机制 ...

  7. MySQL大量脏数据,如何只保留最新的一条?

    因为系统的一个Bug,导致数据库表中出现重复数据,需要做的是删除重复数据且只保留最新的一条数据. 具体场景是这样的 有张订单关联额外费用表,而且一个订单号(order_no)记录只能关联同一个费用(c ...

  8. Junit启动测试mybatis xml文件BindingException: Invalid bound statement问题

    背景:1.正常启动,xml文件放在java目录和resource目录下均正常 2.junit启动,xml文件放在resource目录下正常,放在java目录下报BindingException错误 m ...

  9. [操作系统] - 进程切换&进程控制

    2.1.6 进程切换 名称解析 进程的上下文(Context) 当一个进程在执行时,CPU的所有寄存器的值.进程的状态以及堆栈中的内容被称为进程的上下文Context 进程的切换(switch) 当内 ...

  10. MDC轻量化日志链路跟踪的若干种应用场景

    "If debugging is the process of removing software bugs, then programming must be the process of ...