• 尚医通项目124-149:微信登录以及阿里云OSS的使用


    开始时间:2022-06-17
    课程链接:尚医通项目

    微信登录

    OAuth2

    • 开放系统间授权
      照片拥有者想要在云冲印服务上打印照片,云冲印服务需要访问云存储服务上的资源
      方式一:用户名密码复制:将受保护的资源中的用户名和密码存储在客户应用的服务器上,使用时直接使用这个用户名和密码登录适用于同一公司内部的多个系统,不适用于不受信的第三方应用
      方式二:通用开发者key,适用于合作商或者授信的不同业务部门之间,但如果公司规模体量不对等,也不会去开通这项业务
      ==方式三:颁发令牌,==可以设置令牌有效时间,在这段时间允许访问,可以随时收回

    • 单点登录
      在这里插入图片描述
      现代微服务中系统微服务化以及应用的形态和设备类型增多,不能用传统的登录方式
      核心的技术不是用户名和密码,而是token,由AuthServer颁发token,用户使用token进行登录

    微信登录前期准备有些麻烦,参考文档
    这里老师直接给了他的一个用户

    操作模块:service-user
    我们的操作步骤为:

    • 第一步我们通过接口把对应参数返回页面;
    • 第二步在头部页面启动打开微信登录二维码;
    • 第三步处理登录回调接口;
    • 第四步回调返回页面通知微信登录层回调成功
    • 第五步如果是第一次扫描登录,则绑定邮箱号码,登录成功

    在application-dev.yml添加配置

    # 服务端口
    server.port=8160
    wx.open.app_id=wxed9954c01bb89b47
    wx.open.app_secret=a7482517235173ddb4083788de60b90e
    wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback
    yygh.baseUrl=http://localhost:3000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    看看效果
    正常微信扫码的样子
    调用流程
    添加配置
    service_user下

    wx.open.app_id=wxed9954c01bb89b47
    wx.open.app_secret=a7482517235173ddb4083788de60b90e
    wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback
    yygh.baseUrl=http://localhost:3000
    
    • 1
    • 2
    • 3
    • 4

    添加配置类

    package com.bupt.yygh.user.utils;
    
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ConstantWxPropertiesUtils implements InitializingBean {
    
        @Value("${wx.open.app_id}")
        private String appId;
    
        @Value("${wx.open.app_secret}")
        private String appSecret;
    
        @Value("${wx.open.redirect_url}")
        private String redirectUrl;
    
        @Value("${yygh.baseUrl}")
        private String yyghBaseUrl;
    
    
        public static String WX_OPEN_APP_ID;
        public static String WX_OPEN_APP_SECRET;
        public static String WX_OPEN_REDIRECT_URL;
        public static String YYGH_BASE_URL;
    
    
        @Override
        public void afterPropertiesSet() throws Exception {
            WX_OPEN_APP_ID = appId;
            WX_OPEN_APP_SECRET = appSecret;
            WX_OPEN_REDIRECT_URL = redirectUrl;
            YYGH_BASE_URL = yyghBaseUrl;
        }
    }
    
    
    • 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

    添加接口

    package com.bupt.yygh.user.api;
    
    import com.alibaba.fastjson.JSONObject;
    import com.bupt.yygh.common.helper.JwtHelper;
    import com.bupt.yygh.common.result.Result;
    import com.bupt.yygh.model.user.UserInfo;
    import com.bupt.yygh.user.service.UserInfoService;
    import com.bupt.yygh.user.utils.ConstantWxPropertiesUtils;
    
    import com.bupt.yygh.user.utils.HttpClientUtils;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.util.StringUtils;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.util.HashMap;
    import java.util.Map;
    
    @Api(tags = "微信扫码登录服务")
    //微信操作的接口
    @Controller
    //用Controller为了跳转方便
    // 但是这里不是RestController,所以我们下面要自己补充ResponseBody
    @RequestMapping("/api/ucenter/wx")
    public class WeixinApiController {
    
        @Autowired
        private UserInfoService userInfoService;
    
        //1 生成微信扫描二维码
        //返回生成二维码需要参数
        @GetMapping("getLoginParam")
        @ResponseBody
        @ApiOperation("生成微信扫码二维码")
        public Result genQrConnect() {
            try {
                Map<String, Object> map = new HashMap<>();
                map.put("appid", ConstantWxPropertiesUtils.WX_OPEN_APP_ID);
                map.put("scope", "snsapi_login");
                String wxOpenRedirectUrl = ConstantWxPropertiesUtils.WX_OPEN_REDIRECT_URL;
                wxOpenRedirectUrl = URLEncoder.encode(wxOpenRedirectUrl, "utf-8");
                //注意传参和后端一致
                map.put("redirect_uri", wxOpenRedirectUrl);
                map.put("state", System.currentTimeMillis() + "");
                return Result.ok(map);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return null;
            }
        }
    
        //微信扫描后回调的方法
        @GetMapping("callback")
        public String callback(String code, String state) {
            //第一步 获取临时票据 code
            System.out.println("code:" + code);
            //第二步 拿着code和微信id和秘钥,请求微信固定地址 ,得到两个值
    
            //使用code和appid以及appscrect换取access_token
            //  %s   占位符
            StringBuffer baseAccessTokenUrl = new StringBuffer()
                    .append("https://api.weixin.qq.com/sns/oauth2/access_token")
                    .append("?appid=%s")
                    .append("&secret=%s")
                    .append("&code=%s")
                    .append("&grant_type=authorization_code");
            String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),
                    ConstantWxPropertiesUtils.WX_OPEN_APP_ID,
                    ConstantWxPropertiesUtils.WX_OPEN_APP_SECRET,
                    code);
            //使用httpclient请求这个地址
            try {
                String accesstokenInfo = HttpClientUtils.get(accessTokenUrl);
                System.out.println("accesstokenInfo:" + accesstokenInfo);
                //从返回字符串获取两个值 openid  和  access_token
                JSONObject jsonObject = JSONObject.parseObject(accesstokenInfo);
                String access_token = jsonObject.getString("access_token");
                String openid = jsonObject.getString("openid");
    
                //判断数据库是否存在微信的扫描人信息
                //根据openid判断
                UserInfo userInfo = userInfoService.selectWxInfoOpenId(openid);
                if (userInfo == null) { //数据库不存在微信信息
                    //  第三步 拿着openid 和 access_token请求微信地址,得到扫描人信息
                    String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                            "?access_token=%s" +
                            "&openid=%s";
                    String userInfoUrl = String.format(baseUserInfoUrl, access_token, openid);
                    String resultInfo = HttpClientUtils.get(userInfoUrl);
                    System.out.println("resultInfo:" + resultInfo);
                    JSONObject resultUserInfoJson = JSONObject.parseObject(resultInfo);
                    //解析用户信息
                    //用户昵称
                    String nickname = resultUserInfoJson.getString("nickname");
                    //用户头像
                    String headimgurl = resultUserInfoJson.getString("headimgurl");
    
                    //获取扫描人信息添加数据库
                    userInfo = new UserInfo();
                    userInfo.setNickName(nickname);
                    userInfo.setOpenid(openid);
                    userInfo.setStatus(1);
                    userInfoService.save(userInfo);
                }
                //返回name和token字符串
                Map<String, String> map = new HashMap<>();
                String name = userInfo.getName();
                if (StringUtils.isEmpty(name)) {
                    name = userInfo.getNickName();
                }
                if (StringUtils.isEmpty(name)) {
                    name = userInfo.getEmail();
                }
                map.put("name", name);
    
                //判断userInfo是否有邮箱号,如果邮箱号为空,返回openid
                //如果邮箱号不为空,返回openid值是空字符串
                //前端判断:如果openid不为空,绑定邮箱号,如果openid为空,不需要绑定邮箱号
                if (StringUtils.isEmpty(userInfo.getEmail())) {
                    map.put("openid", userInfo.getOpenid());
                } else {
                    map.put("openid", "");
                }
                //使用jwt生成token字符串
                String token = JwtHelper.createToken(userInfo.getId(), name);
                map.put("token", token);
                //跳转到前端页面
                return "redirect:" + ConstantWxPropertiesUtils.YYGH_BASE_URL + "/weixin/callback?token=" + map.get("token") + "&openid=" + map.get("openid") +
                        "&name=" + URLEncoder.encode(map.get("name"), "utf-8");
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    
    
    • 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

    注意:

    //微服务的service-user的端口号
    ★ 第一   修改项目启动端口号为 8160 
    ★ 第二步 把回调地址改为 wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback
    
    • 1
    • 2
    • 3

    具体完整代码参考Gitee第十五次更新

    在这里插入图片描述
    跳转过程
    在这里插入图片描述

    我把微信跑通了之后,发现之前的微服务反而用不了了
    报错
    在这里插入图片描述

    在这里插入图片描述
    我测试swagger以及看我的网关服务,都是没问题的
    然后我发现是因为网关的配置问题
    为了完成刚刚微信扫码的功能,添加了一个过滤器,把过滤器注释掉后就能用了,我也就不改过滤器本身的配置了

    OSS

    用户认证需要上传证件图片、首页轮播也需要上传图片,因此我们要做文件服务,阿里云oss是一个很好的分布式文件服务系统,所以我们只需要集成阿里云oss即可

    创建一个OSS

    阿里云里面创建OSS

    创建一个bucket
    在这里插入图片描述
    在这里插入图片描述

    在文件管理中上传文件
    在这里插入图片描述
    通过url路径访问地址
    在这里插入图片描述
    获取对应的accessKey
    在这里插入图片描述
    通过代码创建bucket,注意不能跟已有bucket同名,否则会报错

    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.model.CreateBucketRequest;
    
    public class test {
        public static void main(String[] args) {
            // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
            String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
            // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
            String accessKeyId = "LTAI5tNKutqsvWPSXAuSg679";
            String accessKeySecret = "vwynb14tvmrJOJFsE4MKH8z6Tk6FNS";
            // 填写Bucket名称,例如examplebucket。
            String bucketName = "yygh-test-oss-jdh";
    
            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    
            try {
                // 创建CreateBucketRequest对象。
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
    
                // 如果创建存储空间的同时需要指定存储类型和数据容灾类型, 请参考如下代码。
                // 此处以设置存储空间的存储类型为标准存储为例介绍。
                //createBucketRequest.setStorageClass(StorageClass.Standard);
                // 数据容灾类型默认为本地冗余存储,即DataRedundancyType.LRS。如果需要设置数据容灾类型为同城冗余存储,请设置为DataRedundancyType.ZRS。
                //createBucketRequest.setDataRedundancyType(DataRedundancyType.ZRS);
                // 设置存储空间的权限为公共读,默认为私有。
                //createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
    
                // 创建存储空间。
                ossClient.createBucket(createBucketRequest);
            } 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());
            } catch (ClientException 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());
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
    }
    
    
    • 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

    生成成功
    在这里插入图片描述

    上传文件到阿里云端口里面去

    在这里插入图片描述

    实名认证功能

    在service_user中的UserInfoAPIController写上

       //用户认证接口
        @PostMapping("auth/userAuth")
        public Result userAuth(@RequestBody UserAuthVo userAuthVo, HttpServletRequest request) {
            //传递两个参数,第一个参数用户id,第二个参数认证数据vo对象
            userInfoService.userAuth(AuthContextHolder.getUserId(request),userAuthVo);
            return Result.ok();
        }
        
        //获取用户id信息接口
        @GetMapping("auth/getUserInfo")
        public Result getUserInfo(HttpServletRequest request) {
            Long userId = AuthContextHolder.getUserId(request);
            UserInfo userInfo = userInfoService.getById(userId);
            return Result.ok(userInfo);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    对应接口实现类

    //用户认证
        @Override
        public void userAuth(Long userId, UserAuthVo userAuthVo) {
            //根据用户id查询用户信息
            UserInfo userInfo = baseMapper.selectById(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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    前端页面copy过来的,看下面效果

    在这里插入图片描述
    在这里插入图片描述
    可以查看数据库的yygh_user里面,将certificate也填上了
    在这里插入图片描述

    就诊人管理

    因为认证了的账号可以给亲属挂号
    看看效果
    在user_info表中
    在这里插入图片描述
    在patient表中
    在这里插入图片描述
    注意patient的user_id要和user_info里面对应
    就可以查看到结果
    在这里插入图片描述
    点击查看详情
    在这里插入图片描述
    修改
    在这里插入图片描述
    添加
    在这里插入图片描述
    在这里插入图片描述

    具体代码还是得看码云对应的第十八次更新

    平台用户管理

    用户列表功能的实现

    在这里插入图片描述
    这一块是在9528页面上操作的,不能搞错了
    如果启动自己的微服务显示端口被占用,不要慌,关掉idea重启一下

    用户锁定功能

    在这里插入图片描述

    在这里插入图片描述

    用户详情功能

    在这里插入图片描述
    点击查看,可以看到详细信息
    在这里插入图片描述

    用户认证审批

    先在列表里找到,只有auth_status为1的数据才能显示
    在这里插入图片描述
    点击通过后可以看到数据库里的值得到了更新

    在这里插入图片描述
    整个平台用户管理的代码参考码云的更新:第十九次更新,完成了平台管理功能:用户列表功能、用户锁定功能、用户详情功能、用户认证审批
    结束时间:2022-06-25

  • 相关阅读:
    C++11的更新内容--左值引用--1114
    【Java基础系列】运算符和类型转换
    优化|优化求解器自动调参
    SQL Server Not Null约束
    openfeign客户端A调用服务B,服务B抛出异常时,客户端A接收的几种情况
    Linux - lsof显示 tcp,udp 的端口和进程
    第二十篇-推荐-纯CPU(E5-2680)推理-llama.cpp-qwen1_5-72b-chat-q4_k_m.gguf
    Spring
    【2012NOIP普及组】T4. 文化之旅 试题解析
    骨感传导蓝牙耳机怎么样,骨感传导耳机对于我们耳道有保护吗
  • 原文地址:https://blog.csdn.net/qq_43568982/article/details/125336421