|
|
|
|
# 商城认证服务
|
|
|
|
|
|
|
|
|
|
# 一、搭建认证服务环境
|
|
|
|
|
|
|
|
|
|
  结合我们前面介绍的商城的架构我们需要单独的搭建一个认证服务。
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/6e06e02a4c8d4f4d8af8d9b38ab2e4f3.png)
|
|
|
|
|
|
|
|
|
|
## 1.创建项目
|
|
|
|
|
|
|
|
|
|
  首先创建一个SpringBoot项目,然后添加对应的依赖
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
|
|
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
|
|
|
<modelVersion>4.0.0</modelVersion>
|
|
|
|
|
<parent>
|
|
|
|
|
<groupId>org.springframework.boot</groupId>
|
|
|
|
|
<artifactId>spring-boot-starter-parent</artifactId>
|
|
|
|
|
<version>2.4.12</version>
|
|
|
|
|
<relativePath/> <!-- lookup parent from repository -->
|
|
|
|
|
</parent>
|
|
|
|
|
<groupId>com.msb.mall</groupId>
|
|
|
|
|
<artifactId>mall-auth-server</artifactId>
|
|
|
|
|
<version>0.0.1-SNAPSHOT</version>
|
|
|
|
|
<name>mall-auth_server</name>
|
|
|
|
|
<description>认证服务</description>
|
|
|
|
|
<properties>
|
|
|
|
|
<java.version>1.8</java.version>
|
|
|
|
|
<spring-cloud.version>2020.0.1</spring-cloud.version>
|
|
|
|
|
</properties>
|
|
|
|
|
<dependencies>
|
|
|
|
|
<!-- 公共依赖 -->
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>com.msb.mall</groupId>
|
|
|
|
|
<artifactId>mall-commons</artifactId>
|
|
|
|
|
<version>0.0.1-SNAPSHOT</version>
|
|
|
|
|
<exclusions>
|
|
|
|
|
<exclusion>
|
|
|
|
|
<groupId>com.baomidou</groupId>
|
|
|
|
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
|
|
|
|
</exclusion>
|
|
|
|
|
</exclusions>
|
|
|
|
|
</dependency>
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.boot</groupId>
|
|
|
|
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
|
|
|
|
</dependency>
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.boot</groupId>
|
|
|
|
|
<artifactId>spring-boot-starter-web</artifactId>
|
|
|
|
|
</dependency>
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.cloud</groupId>
|
|
|
|
|
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
|
|
|
|
</dependency>
|
|
|
|
|
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.boot</groupId>
|
|
|
|
|
<artifactId>spring-boot-devtools</artifactId>
|
|
|
|
|
<scope>runtime</scope>
|
|
|
|
|
<optional>true</optional>
|
|
|
|
|
</dependency>
|
|
|
|
|
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.boot</groupId>
|
|
|
|
|
<artifactId>spring-boot-starter-test</artifactId>
|
|
|
|
|
<scope>test</scope>
|
|
|
|
|
</dependency>
|
|
|
|
|
</dependencies>
|
|
|
|
|
<dependencyManagement>
|
|
|
|
|
<dependencies>
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.cloud</groupId>
|
|
|
|
|
<artifactId>spring-cloud-dependencies</artifactId>
|
|
|
|
|
<version>${spring-cloud.version}</version>
|
|
|
|
|
<type>pom</type>
|
|
|
|
|
<scope>import</scope>
|
|
|
|
|
</dependency>
|
|
|
|
|
</dependencies>
|
|
|
|
|
</dependencyManagement>
|
|
|
|
|
|
|
|
|
|
<build>
|
|
|
|
|
<plugins>
|
|
|
|
|
<plugin>
|
|
|
|
|
<groupId>org.springframework.boot</groupId>
|
|
|
|
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
|
|
|
<configuration>
|
|
|
|
|
<excludes>
|
|
|
|
|
<exclude>
|
|
|
|
|
<groupId>org.projectlombok</groupId>
|
|
|
|
|
<artifactId>lombok</artifactId>
|
|
|
|
|
</exclude>
|
|
|
|
|
</excludes>
|
|
|
|
|
</configuration>
|
|
|
|
|
</plugin>
|
|
|
|
|
</plugins>
|
|
|
|
|
</build>
|
|
|
|
|
|
|
|
|
|
</project>
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 2.注册中心配置
|
|
|
|
|
|
|
|
|
|
  我们需要把认证服务注册到Nacos中,添加对应的依赖,然后完成对应的配置
|
|
|
|
|
|
|
|
|
|
```properties
|
|
|
|
|
# Nacos服务注册
|
|
|
|
|
spring:
|
|
|
|
|
cloud:
|
|
|
|
|
nacos:
|
|
|
|
|
discovery:
|
|
|
|
|
server-addr: 192.168.56.100:8848
|
|
|
|
|
application:
|
|
|
|
|
name: mall-auth_server
|
|
|
|
|
# 统一的全局的--设置服务器响应给客户端的日期时间格式
|
|
|
|
|
jackson:
|
|
|
|
|
date-format: yyyy-MM-dd HH:mm:ss
|
|
|
|
|
thymeleaf:
|
|
|
|
|
cache: false # 关闭Thymeleaf的缓存
|
|
|
|
|
server:
|
|
|
|
|
port: 30000
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
放开Nacos注册中心
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/caf33f23f60a49b2929ae46f20386068.png)
|
|
|
|
|
|
|
|
|
|
然后启动测试
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/42b66d7705cd45d88ceff0299efd1bdb.png)
|
|
|
|
|
|
|
|
|
|
## 3.登录和注册页面
|
|
|
|
|
|
|
|
|
|
  然后我们整理登录和注册的相关资源,首先把登录和注册的模板文件拷贝进项目
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/2eab568483cc4551bf8a1fcc32432cee.png)
|
|
|
|
|
|
|
|
|
|
然后把对应的静态文件拷贝到Nginx中。
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/0a9f8e13aca5493893aaf8f844845422.png)
|
|
|
|
|
|
|
|
|
|
然后我们需要在host文件中添加对应的配置
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/704667a877ec4c7daec5355f885fb721.png)
|
|
|
|
|
|
|
|
|
|
修改Nginx的反向代理的配置
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/63fac10a01724a40bbaa68ca8f187d06.png)
|
|
|
|
|
|
|
|
|
|
然后重启Nginx的服务![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/82c83ec09182425c9ed8e8b853a38ddc.png)
|
|
|
|
|
|
|
|
|
|
然后修改网关服务
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/688c595a337f4c24b0ad002c1fda168a.png)
|
|
|
|
|
|
|
|
|
|
最后调整登录和注册页面的静态资源文件的路径.
|
|
|
|
|
|
|
|
|
|
注册服务的名称:msb-auth,启动对应的服务,测试
|
|
|
|
|
|
|
|
|
|
登录页面
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/a51ce9f85e4042f182bc8209988b6d95.png)
|
|
|
|
|
|
|
|
|
|
注册页面
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/810653907e894eb0a3d5667964309e4e.png)
|
|
|
|
|
|
|
|
|
|
## 4.注册功能
|
|
|
|
|
|
|
|
|
|
### 4.1 手机验证码
|
|
|
|
|
|
|
|
|
|
  先处理验证码的页面,使其能够倒数操作
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/fa2899f54403470d81c61e8b9e214ec9.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/4f9b125be7354345a86817493164c07e.png)
|
|
|
|
|
|
|
|
|
|
JS代码
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
$(function(){
|
|
|
|
|
$("#sendCode").click(function(){
|
|
|
|
|
if($(this).hasClass("d1")){
|
|
|
|
|
// 说明正在倒计时
|
|
|
|
|
}else{
|
|
|
|
|
// 给指定的手机号发送验证码
|
|
|
|
|
timeoutChangeStyle()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
var num = 10
|
|
|
|
|
function timeoutChangeStyle(){
|
|
|
|
|
$("#sendCode").attr("class","d1")
|
|
|
|
|
if(num == 0){
|
|
|
|
|
// 说明1分钟到了,可以再次发送验证码了
|
|
|
|
|
$("#sendCode").text("发送验证码")
|
|
|
|
|
num= 10;
|
|
|
|
|
$("#sendCode").attr("class","")
|
|
|
|
|
}else{
|
|
|
|
|
setTimeout('timeoutChangeStyle()',1000)
|
|
|
|
|
$("#sendCode").text(num+"s后再次发送")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
num --;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 4.2 短信验证接口
|
|
|
|
|
|
|
|
|
|
  通过阿里云的短信服务来实现。我们直接购买0元15次就可以了。https://www.aliyun.com/
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/57ed73c529b441ecad8a8dd7906d636b.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/e9f4f52eaf3d412cac3c4fb0bcb62638.png)
|
|
|
|
|
|
|
|
|
|
进入到对应的管理控制台,查看对应的信息
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/803a91dae1444dd5b75ac7b233ab00b2.png)
|
|
|
|
|
|
|
|
|
|
通过短信供应商提供的相关的编程语言的开发模板开发即可
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/9a048fe06aa648648498444126d5c2ca.png)
|
|
|
|
|
|
|
|
|
|
供应商提供了对应的HttpUtils工具类,我们需要下载保存到我们自己的项目中。
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/5cd7e92a1e064fc9b381e7e42ad2df12.png)
|
|
|
|
|
|
|
|
|
|
然后封装对应的发送验证码的接口
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
package com.msb.mall.third.utils;
|
|
|
|
|
|
|
|
|
|
import lombok.Data;
|
|
|
|
|
import org.apache.http.HttpResponse;
|
|
|
|
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 短信组件
|
|
|
|
|
*/
|
|
|
|
|
@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms")
|
|
|
|
|
@Data
|
|
|
|
|
@Component
|
|
|
|
|
public class SmsComponent {
|
|
|
|
|
|
|
|
|
|
private String host;
|
|
|
|
|
private String path;
|
|
|
|
|
private String method = "POST";
|
|
|
|
|
private String appCode;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 发送短信验证码
|
|
|
|
|
* @param phone 发送的手机号
|
|
|
|
|
* @param code 发送的短信验证码
|
|
|
|
|
*/
|
|
|
|
|
public void sendSmsCode(String phone,String code){
|
|
|
|
|
Map<String, String> headers = new HashMap<String, String>();
|
|
|
|
|
//最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
|
|
|
|
|
headers.put("Authorization", "APPCODE " + appCode);
|
|
|
|
|
//根据API的要求,定义相对应的Content-Type
|
|
|
|
|
headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
|
|
|
|
Map<String, String> querys = new HashMap<String, String>();
|
|
|
|
|
Map<String, String> bodys = new HashMap<String, String>();
|
|
|
|
|
bodys.put("content", "code:"+code);
|
|
|
|
|
bodys.put("phone_number", phone);
|
|
|
|
|
bodys.put("template_id", "TPL_0000");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
|
|
|
|
|
System.out.println(response.toString());
|
|
|
|
|
//获取response的body
|
|
|
|
|
//System.out.println(EntityUtils.toString(response.getEntity()));
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
添加对应的属性信息
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/14f2c82e543347339e46cc3c5698d00c.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/1cc1456012214728ae5d3ab3a3cb1a47.png)
|
|
|
|
|
|
|
|
|
|
### 4.3 短信功能
|
|
|
|
|
|
|
|
|
|
  然后我们将短信功能串联起来
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/85da38b9837c46e4b7c2f4da43bc8966.png)
|
|
|
|
|
|
|
|
|
|
#### 4.3.1 third服务
|
|
|
|
|
|
|
|
|
|
  我们需要在第三方服务中提供对外的接口服务
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
@RestController
|
|
|
|
|
public class SMSController {
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private SmsComponent smsComponent;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 调用短信服务商提供的短信API发送短信
|
|
|
|
|
* @param phone
|
|
|
|
|
* @param code
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
@GetMapping("/sms/sendcode")
|
|
|
|
|
public R sendSmsCode(@RequestParam("phone") String phone,@RequestParam("code") String code){
|
|
|
|
|
smsComponent.sendSmsCode(phone,code);
|
|
|
|
|
return R.ok();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/df8b549c0a6b4b8781beb8a40acb443c.png)
|
|
|
|
|
|
|
|
|
|
#### 4.3.2 认证服务
|
|
|
|
|
|
|
|
|
|
  我们需要在认证服务中通过feign来调用third中提供的短信服务,同时给客户端提供访问的接口
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.cloud</groupId>
|
|
|
|
|
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
|
|
|
|
</dependency>
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.cloud</groupId>
|
|
|
|
|
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
|
|
|
|
</dependency>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
放开注解
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/4c43c32eb0684661b6f0fb73bdbf416d.png)
|
|
|
|
|
|
|
|
|
|
然后声明Feign的接口
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/78d4f48f38254350bde42bc08f873f46.png)
|
|
|
|
|
|
|
|
|
|
定义对应的Controller
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
@Controller
|
|
|
|
|
public class LoginController {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private ThirdPartFeginService thirdPartFeginService;
|
|
|
|
|
|
|
|
|
|
@ResponseBody
|
|
|
|
|
@GetMapping("/sms/sendCode")
|
|
|
|
|
public R sendSmsCode(@RequestParam("phone") String phone){
|
|
|
|
|
// 生成随机的验证码
|
|
|
|
|
String code = UUID.randomUUID().toString().substring(0, 5);
|
|
|
|
|
thirdPartFeginService.sendSmsCode(phone,code);
|
|
|
|
|
return R.ok();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 4.3.3 客户端
|
|
|
|
|
|
|
|
|
|
  然后我们需要在页面中通过jQuery的异步提交来发送短信
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/af9d02f2a6a84261b466655b422cf252.png)
|
|
|
|
|
|
|
|
|
|
#### 4.3.4 验证码存储
|
|
|
|
|
|
|
|
|
|
  当我们把验证码通过短信的形式发送给你客户手机,然后我们需要把手机号和对应的验证码存储起来,后面可能会集群部署,这时我们把这个信息存在在Redis中。
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/27c5d3fce4164fc2a2b0a128622d3b87.png)
|
|
|
|
|
|
|
|
|
|
添加配置
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/5566599b09d348c5b5fe6f1e34f0597e.png)
|
|
|
|
|
|
|
|
|
|
存储数据
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/92d226010da1473b9adbeafb9f6afd6f.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/c27951de26314a01b58aa4c3d7c173a3.png)、
|
|
|
|
|
|
|
|
|
|
搞定
|
|
|
|
|
|
|
|
|
|
#### 4.3.5 60秒间隔
|
|
|
|
|
|
|
|
|
|
  针对验证码发送的间隔必须是60秒以上,这时我们可以在保存到Redis中的数据的值我们加上发送的时间来处理
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/79b53c42da944421a67bde1c6602f4df.png)
|
|
|
|
|
|
|
|
|
|
模板页面也需要做出对应的处理
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/21ef90379a8e4f56b7b8c555463c074a.png)
|
|
|
|
|
|
|
|
|
|
### 4.4 注册数据验证
|
|
|
|
|
|
|
|
|
|
  表单提交的注册数据我们通过JSR303来验证。
|
|
|
|
|
|
|
|
|
|
首先定义VO对象
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
package com.msb.mall.vo;
|
|
|
|
|
|
|
|
|
|
import lombok.Data;
|
|
|
|
|
import org.hibernate.validator.constraints.Length;
|
|
|
|
|
|
|
|
|
|
import javax.validation.constraints.NotEmpty;
|
|
|
|
|
import javax.validation.constraints.Pattern;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 注册用户的VO对象
|
|
|
|
|
*/
|
|
|
|
|
@Data
|
|
|
|
|
public class UserRegisterVo {
|
|
|
|
|
|
|
|
|
|
@NotEmpty(message = "账号不能为空")
|
|
|
|
|
@Length(min = 3,max = 15,message = "账号必须是3~15位")
|
|
|
|
|
private String userName; // 账号
|
|
|
|
|
|
|
|
|
|
@NotEmpty(message = "密码不能为空")
|
|
|
|
|
@Length(min = 3,max = 15,message = "密码必须是3~15位")
|
|
|
|
|
private String password; // 密码
|
|
|
|
|
|
|
|
|
|
@NotEmpty(message = "手机号不能为空")
|
|
|
|
|
@Pattern(regexp = "^[1][3-9][0-9]{9}$",message = "手机号不合法")
|
|
|
|
|
private String phone; // 手机号
|
|
|
|
|
|
|
|
|
|
@NotEmpty(message = "验证码不能为空")
|
|
|
|
|
private String code; // 验证码
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
然后就是控制器的逻辑代码
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
@PostMapping("/sms/register")
|
|
|
|
|
public String register(@Valid UserRegisterVo vo, BindingResult result, Model model){
|
|
|
|
|
if(result.hasErrors()){
|
|
|
|
|
// 表示提交的数据不合法
|
|
|
|
|
List<FieldError> fieldErrors = result.getFieldErrors();
|
|
|
|
|
Map<String,String> map = new HashMap<>();
|
|
|
|
|
for (FieldError fieldError : fieldErrors) {
|
|
|
|
|
String field = fieldError.getField();
|
|
|
|
|
String defaultMessage = fieldError.getDefaultMessage();
|
|
|
|
|
map.put(field,defaultMessage);
|
|
|
|
|
}
|
|
|
|
|
model.addAttribute("error",map);
|
|
|
|
|
return "/reg";
|
|
|
|
|
}
|
|
|
|
|
// 表单提交的注册的数据是合法的
|
|
|
|
|
|
|
|
|
|
return "redirect:/login.html";
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
然后就是页面代码处理
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/1b2053f62c3e412bb7f515fa69647eb4.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/d0a1d66eaa824edc936ac8b914961238.png)
|
|
|
|
|
|
|
|
|
|
验证码的校验
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/e8895b66d8e449efb410578563a94715.png)
|
|
|
|
|
|
|
|
|
|
### 4.5 完整的注册功能
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/4f4b98662f5c4a8d89580ffedaff9a46.png)
|
|
|
|
|
|
|
|
|
|
会员服务处理
|
|
|
|
|
|
|
|
|
|
控制器
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
/**
|
|
|
|
|
* 会员注册
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
@PostMapping("/register")
|
|
|
|
|
public R register(@RequestBody MemberReigerVO vo){
|
|
|
|
|
try {
|
|
|
|
|
memberService.register(vo);
|
|
|
|
|
}catch (UsernameExsitException exception){
|
|
|
|
|
return R.error(BizCodeEnume.USERNAME_EXSIT_EXCEPTION.getCode(),
|
|
|
|
|
BizCodeEnume.USERNAME_EXSIT_EXCEPTION.getMsg());
|
|
|
|
|
}catch (PhoneExsitExecption exsitExecption) {
|
|
|
|
|
return R.error(BizCodeEnume.PHONE_EXSIT_EXCEPTION.getCode(),
|
|
|
|
|
BizCodeEnume.PHONE_EXSIT_EXCEPTION.getMsg());
|
|
|
|
|
}catch (Exception e){
|
|
|
|
|
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),
|
|
|
|
|
BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return R.ok();
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
然后对应的Service
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
/**
|
|
|
|
|
* 完成会员的注册功能
|
|
|
|
|
* @param vo
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public void register(MemberReigerVO vo) throws PhoneExsitExecption,UsernameExsitException{
|
|
|
|
|
MemberEntity entity = new MemberEntity();
|
|
|
|
|
// 设置会员等级 默认值
|
|
|
|
|
MemberLevelEntity memberLevelEntity = memberLevelService.queryMemberLevelDefault();
|
|
|
|
|
entity.setLevelId(memberLevelEntity.getId()); // 设置默认的会员等级
|
|
|
|
|
|
|
|
|
|
// 添加对应的账号和手机号是不能重复的
|
|
|
|
|
checkUsernameUnique(vo.getUserName());
|
|
|
|
|
checkPhoneUnique(vo.getPhone());
|
|
|
|
|
|
|
|
|
|
entity.setUsername(vo.getUserName());
|
|
|
|
|
entity.setMobile(vo.getPhone());
|
|
|
|
|
|
|
|
|
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
|
|
|
|
String encode = encoder.encode(vo.getPassword());
|
|
|
|
|
// 需要对密码做加密处理
|
|
|
|
|
entity.setPassword(encode);
|
|
|
|
|
// 设置其他的默认值
|
|
|
|
|
this.save(entity);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
auth服务通过Fegin远程调用
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/aa01b1185c9544058ee838c2ef190e43.png)
|
|
|
|
|
|
|
|
|
|
远程调用
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
@PostMapping("/sms/register")
|
|
|
|
|
public String register(@Valid UserRegisterVo vo, BindingResult result, Model model){
|
|
|
|
|
Map<String,String> map = new HashMap<>();
|
|
|
|
|
if(result.hasErrors()){
|
|
|
|
|
// 表示提交的数据不合法
|
|
|
|
|
List<FieldError> fieldErrors = result.getFieldErrors();
|
|
|
|
|
|
|
|
|
|
for (FieldError fieldError : fieldErrors) {
|
|
|
|
|
String field = fieldError.getField();
|
|
|
|
|
String defaultMessage = fieldError.getDefaultMessage();
|
|
|
|
|
map.put(field,defaultMessage);
|
|
|
|
|
}
|
|
|
|
|
model.addAttribute("error",map);
|
|
|
|
|
return "/reg";
|
|
|
|
|
}else{
|
|
|
|
|
// 验证码是否正确
|
|
|
|
|
String code = (String)redisTemplate.opsForValue().get(SMSConstant.SMS_CODE_PERFIX + vo.getPhone());
|
|
|
|
|
code = code.split("_")[0];
|
|
|
|
|
if(!code.equals(vo.getCode())){
|
|
|
|
|
// 说明验证码不正确
|
|
|
|
|
map.put("code","验证码错误");
|
|
|
|
|
model.addAttribute("error",map);
|
|
|
|
|
return "/reg";
|
|
|
|
|
}else{
|
|
|
|
|
// 验证码正确 删除验证码
|
|
|
|
|
redisTemplate.delete(SMSConstant.SMS_CODE_PERFIX + vo.getPhone());
|
|
|
|
|
// 远程调用对应的服务 完成注册功能
|
|
|
|
|
R r = memberFeginService.register(vo);
|
|
|
|
|
if(r.getCode() == 0){
|
|
|
|
|
// 注册成功
|
|
|
|
|
return "redirect:http://msb.auth.com/login.html";
|
|
|
|
|
}else{
|
|
|
|
|
// 注册失败
|
|
|
|
|
map.put("msg",r.getCode()+":"+r.get("msg"));
|
|
|
|
|
model.addAttribute("error",map);
|
|
|
|
|
return "/reg";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//return "redirect:/login.html";
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
完成对应的服务注册
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/72ccce0588b54d758cceba235c8a6957.png)
|
|
|
|
|
|
|
|
|
|
校验提示
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/8d8794dda80045669cc4684390b1831f.png)
|
|
|
|
|
|
|
|
|
|
## 5.登录功能
|
|
|
|
|
|
|
|
|
|
  通过最基础的登录操作来完成登录处理
|
|
|
|
|
|
|
|
|
|
登录页面处理
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/76135367f5aa49f6b39d8380dd614739.png)
|
|
|
|
|
|
|
|
|
|
认证服务的处理
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 注册的方法
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
@PostMapping("/login")
|
|
|
|
|
public String login(LoginVo loginVo , RedirectAttributes redirectAttributes){
|
|
|
|
|
R r = memberFeginService.login(loginVo);
|
|
|
|
|
if(r.getCode() == 0){
|
|
|
|
|
// 表示登录成功
|
|
|
|
|
return "redirect:http://msb.mall.com/home";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
redirectAttributes.addAttribute("errors",r.get("msg"));
|
|
|
|
|
|
|
|
|
|
// 表示登录失败,重新跳转到登录页面
|
|
|
|
|
return "redirect:http://msb.auth.com/login.html";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
会员中心的认证逻辑
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
|
|
|
|
@RequestMapping("/login")
|
|
|
|
|
public R login(@RequestBody MemberLoginVO vo){
|
|
|
|
|
MemberEntity entity = memberService.login(vo);
|
|
|
|
|
if(entity != null){
|
|
|
|
|
return R.ok();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return R.error(BizCodeEnume.USERNAME_PHONE_VALID_EXCEPTION.getCode(),
|
|
|
|
|
BizCodeEnume.USERNAME_PHONE_VALID_EXCEPTION.getMsg());
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
service中的具体认证处理
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
@Override
|
|
|
|
|
public MemberEntity login(MemberLoginVO vo) {
|
|
|
|
|
// 1.根据账号或者手机号来查询会员信息
|
|
|
|
|
MemberEntity entity = this.getOne(new QueryWrapper<MemberEntity>()
|
|
|
|
|
.eq("username", vo.getUserName())
|
|
|
|
|
.or()
|
|
|
|
|
.eq("mobile", vo.getUserName()));
|
|
|
|
|
if(entity != null){
|
|
|
|
|
// 2.如果账号或者手机号存在 然后根据密码加密后的校验来判断是否登录成功
|
|
|
|
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
|
|
|
|
boolean matches = encoder.matches(vo.getPassword(), entity.getPassword());
|
|
|
|
|
if(matches){
|
|
|
|
|
// 表明登录成功
|
|
|
|
|
return entity;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 6.Auth2.0
|
|
|
|
|
|
|
|
|
|
  OAuth2.0是OAuth协议的延续版本,但不向前兼容OAuth 1.0(即完全废止了OAuth1.0)。 OAuth
|
|
|
|
|
2.0关注客户端开发者的简易性。要么通过组织在资源拥有者和HTTP服务商之间的被批准的交互动作代表用户,要么允许第三方应用代表用户获得访问的权限。
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/bf265974f54e42009080c07f02c9e48b.png)
|
|
|
|
|
|
|
|
|
|
### 6.1 微博开放平台
|
|
|
|
|
|
|
|
|
|
地址:https://open.weibo.com/
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/0184cecb32ca41fc8a03bae2f00f724a.png)
|
|
|
|
|
|
|
|
|
|
创建应用
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/8a56466dce7e48019ae77f6eb8511651.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/09d77a9058f246c4a82648081d5124ca.png)
|
|
|
|
|
|
|
|
|
|
创建后的基本信息:
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/3b571819b4a546e88c37406bb78f54ea.png)
|
|
|
|
|
|
|
|
|
|
授权设置:
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/8124143526eb46b18082da3c165ac477.png)
|
|
|
|
|
|
|
|
|
|
社交认证文档:
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/02c7a54d5e754d55a77059ddfbf9a254.png)
|
|
|
|
|
|
|
|
|
|
微博Web端授权的操作:
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/9d5ceaf7ff444687b547dfd86698c4fc.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/853aa396b5d0486b8263170552cc315e.png)
|
|
|
|
|
|
|
|
|
|
引导用户点击按钮跳转到对应的授权页面
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/f5a2c8dbdf2c4b0bbbe0aece7f353bce.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/a25aa1c7417e4b5492d178e8d4a110b4.png)
|
|
|
|
|
|
|
|
|
|
点击授权按钮后查看回调接口的code信息
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/43a9e56e2856430c964caae9a566b6d3.png)
|
|
|
|
|
|
|
|
|
|
获取到了code信息:59d62e59e5ead5a4ea89c6f9cf212568
|
|
|
|
|
|
|
|
|
|
然后根据code信息我们可以去授权服务器获取对应的AccessToken。
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
https://api.weibo.com/oauth2/access_token?client_id=1093598037&client_secret=1085c8de04dee49e9bb110eaf2d3cf62&grant_type=authorization_code&redirect_uri=http://msb.auth.com/success.html&code=59d62e59e5ead5a4ea89c6f9cf212568
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
获取Token信息只支持POST方式提交
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/069e76587c36411393182cb2248d8fd4.png)
|
|
|
|
|
|
|
|
|
|
在PostMan中通过post方式提交成功获取到了对应的token信息
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/cad96be8aef240e7b067044d49b5fff1.png)
|
|
|
|
|
|
|
|
|
|
获取到了Token信息后我们就可以去资源服务器获取对象的信息
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/fb7bd6f5b6554e92bad4871fd11074b4.png)
|
|
|
|
|
|
|
|
|
|
### 6.2 百度开放平台
|
|
|
|
|
|
|
|
|
|
地址:
|
|
|
|
|
|
|
|
|
|
Auth2.0操作:https://developer.baidu.com/wiki/index.php?title=docs/oauth
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/c084707f697848a08f4db1a944cc966b.png)
|
|
|
|
|
|
|
|
|
|
创建应用:http://developer.baidu.com/console#app/project
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/70348f87ddab4ae19c13ce53f826f5d8.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/72d7dd28ddbc48f3aa6f88b6500b7418.png)
|
|
|
|
|
|
|
|
|
|
创建完成:
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/52efc675f6c5433a8b789b39748cb01a.png)
|
|
|
|
|
|
|
|
|
|
引导用户跳转到授权地址:
|
|
|
|
|
|
|
|
|
|
```url
|
|
|
|
|
http://openapi.baidu.com/oauth/2.0/authorize?
|
|
|
|
|
response_type=code&
|
|
|
|
|
client_id=YOUR_CLIENT_ID&
|
|
|
|
|
redirect_uri=YOUR_REGISTERED_REDIRECT_URI&
|
|
|
|
|
scope=email&
|
|
|
|
|
display=popup
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
地址修改为我们自己的:http://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=MmvAkQM7HtrQnKDDhhmTSib5&redirect_uri=http://www.baidu.com&display=popup
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/094f3eb050504ad1b675c1514d504721.png)
|
|
|
|
|
|
|
|
|
|
获取到的Code信息
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/0a568ca08753443a9bfd425049fa0120.png)
|
|
|
|
|
|
|
|
|
|
code:d789d0160b2fa99bb1f840002569526e
|
|
|
|
|
|
|
|
|
|
获取到对应的token信息
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/9a06a84c41d340b4b561deaa1341e8b8.png)
|
|
|
|
|
|
|
|
|
|
Token:121.6966ae0e0f3cd19fa36a375489342b08.YmfrSxYqsOt1eUoPzkC60yCsa7W09OmqTbPsuVL.zmdMFg
|
|
|
|
|
|
|
|
|
|
token访问地址:https://openapi.baidu.com/rest/2.0/passport/users/getLoggedInUser?access_token=121.6966ae0e0f3cd19fa36a375489342b08.YmfrSxYqsOt1eUoPzkC60yCsa7W09OmqTbPsuVL.zmdMFg
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/298c717fd5574e61bf5f178084052897.png)
|
|
|
|
|
|
|
|
|
|
## 7.社交登录实现
|
|
|
|
|
|
|
|
|
|
### 7.1 code处理
|
|
|
|
|
|
|
|
|
|
  在后台服务中获取code并对应的获取Token信息
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/d70c0d96fb444d8188ba7f2d0a09e270.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/dcfcc8e51be2461888bf8892cf7e8f86.png)
|
|
|
|
|
|
|
|
|
|
然后需要同步的调整引入的链接地址:
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/0fcafb42475249eea5de2724be2246a9.png)
|
|
|
|
|
|
|
|
|
|
### 7.2 获取Token信息
|
|
|
|
|
|
|
|
|
|
  根据上一步获取的code信息,我们可以获取对应的Token信息
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
@RequestMapping("/oauth/weibo/success")
|
|
|
|
|
public String weiboOAuth(@RequestParam("code") String code) throws Exception {
|
|
|
|
|
Map<String,String> body = new HashMap<>();
|
|
|
|
|
body.put("client_id","1093598037");
|
|
|
|
|
body.put("client_secret","1085c8de04dee49e9bb110eaf2d3cf62");
|
|
|
|
|
body.put("grant_type","authorization_code");
|
|
|
|
|
body.put("redirect_uri","http://msb.auth.com/oauth/weibo/success");
|
|
|
|
|
body.put("code",code);
|
|
|
|
|
// 根据Code获取对应的Token信息
|
|
|
|
|
HttpResponse post = HttpUtils.doPost("https://api.weibo.com"
|
|
|
|
|
, "/oauth2/access_token"
|
|
|
|
|
, "post"
|
|
|
|
|
, new HashMap<>()
|
|
|
|
|
, null
|
|
|
|
|
, body
|
|
|
|
|
);
|
|
|
|
|
int statusCode = post.getStatusLine().getStatusCode();
|
|
|
|
|
if(statusCode != 200){
|
|
|
|
|
// 说明获取Token失败,就调回到登录页面
|
|
|
|
|
return "redirect:http://msb.auth.com/login.html";
|
|
|
|
|
}
|
|
|
|
|
// 说明获取Token信息成功
|
|
|
|
|
String json = EntityUtils.toString(post.getEntity());
|
|
|
|
|
SocialUser socialUser = JSON.parseObject(json, SocialUser.class);
|
|
|
|
|
// 注册成功就需要调整到商城的首页
|
|
|
|
|
return "redirect:http://msb.mall.com/home.html";
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 7.3 登录和注册
|
|
|
|
|
|
|
|
|
|
  表结构中新增对应的
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/df5d68e8e19e4e67adfcb4eabf4fe310.png)
|
|
|
|
|
|
|
|
|
|
然后在对应的实体对象中添加对应的属性
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/c6b9d25fd0dd4fe49944716ac908dffd.png)
|
|
|
|
|
|
|
|
|
|
service中实现注册和登录的逻辑
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
/**
|
|
|
|
|
* 社交登录
|
|
|
|
|
* @param vo
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public MemberEntity login(SocialUser vo) {
|
|
|
|
|
String uid = vo.getUid();
|
|
|
|
|
// 如果该用户是第一次社交登录,那么需要注册
|
|
|
|
|
// 如果不是第一次社交登录 那么就更新相关信息 登录功能
|
|
|
|
|
MemberEntity memberEntity = this.getOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));
|
|
|
|
|
if(memberEntity != null){
|
|
|
|
|
// 说明当前用户已经注册过了 更新token和过期时间
|
|
|
|
|
MemberEntity entity = new MemberEntity();
|
|
|
|
|
entity.setId(memberEntity.getId());
|
|
|
|
|
entity.setAccessToken(vo.getAccessToken());
|
|
|
|
|
entity.setExpiresIn(vo.getExpiresIn());
|
|
|
|
|
this.updateById(entity);
|
|
|
|
|
// 在返回的登录用户信息中我们同步的也保存 token和过期时间
|
|
|
|
|
memberEntity.setAccessToken(vo.getAccessToken());
|
|
|
|
|
memberEntity.setExpiresIn(vo.getExpiresIn());
|
|
|
|
|
return memberEntity;
|
|
|
|
|
}
|
|
|
|
|
// 表示用户是第一提交,那么我们就需要对应的来注册
|
|
|
|
|
MemberEntity entity = new MemberEntity();
|
|
|
|
|
entity.setAccessToken(vo.getAccessToken());
|
|
|
|
|
entity.setExpiresIn(vo.getExpiresIn());
|
|
|
|
|
entity.setSocialUid(vo.getUid());
|
|
|
|
|
// 通过token调用微博开发的接口来获取用户的相关信息
|
|
|
|
|
try {
|
|
|
|
|
Map<String,String> querys = new HashMap<>();
|
|
|
|
|
querys.put("access_token",vo.getAccessToken());
|
|
|
|
|
querys.put("uid",vo.getUid());
|
|
|
|
|
HttpResponse response = HttpUtils.doGet("https://api.weibo.com"
|
|
|
|
|
, "/2/users/show.json"
|
|
|
|
|
, "get"
|
|
|
|
|
, new HashMap<>()
|
|
|
|
|
, querys
|
|
|
|
|
);
|
|
|
|
|
if(response.getStatusLine().getStatusCode() == 200){
|
|
|
|
|
String json = EntityUtils.toString(response.getEntity());
|
|
|
|
|
JSONObject jsonObject = JSON.parseObject(json);
|
|
|
|
|
String nickName = jsonObject.getString("screen_name");
|
|
|
|
|
String gender = jsonObject.getString("gender");
|
|
|
|
|
entity.setNickname(nickName);
|
|
|
|
|
entity.setGender("m".equals(gender)?1:0);
|
|
|
|
|
}
|
|
|
|
|
}catch (Exception e){
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// 注册用户信息
|
|
|
|
|
this.save(entity);
|
|
|
|
|
return entity;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 7.4 登录的串联
|
|
|
|
|
|
|
|
|
|
在Auth服务中我们需要通过Feign来调用MemberService中的相关服务来完成最后的串联
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
@RequestMapping("/oauth/weibo/success")
|
|
|
|
|
public String weiboOAuth(@RequestParam("code") String code) throws Exception {
|
|
|
|
|
Map<String,String> body = new HashMap<>();
|
|
|
|
|
body.put("client_id","1093598037");
|
|
|
|
|
body.put("client_secret","1085c8de04dee49e9bb110eaf2d3cf62");
|
|
|
|
|
body.put("grant_type","authorization_code");
|
|
|
|
|
body.put("redirect_uri","http://msb.auth.com/oauth/weibo/success");
|
|
|
|
|
body.put("code",code);
|
|
|
|
|
// 根据Code获取对应的Token信息
|
|
|
|
|
HttpResponse post = HttpUtils.doPost("https://api.weibo.com"
|
|
|
|
|
, "/oauth2/access_token"
|
|
|
|
|
, "post"
|
|
|
|
|
, new HashMap<>()
|
|
|
|
|
, null
|
|
|
|
|
, body
|
|
|
|
|
);
|
|
|
|
|
int statusCode = post.getStatusLine().getStatusCode();
|
|
|
|
|
if(statusCode != 200){
|
|
|
|
|
// 说明获取Token失败,就调回到登录页面
|
|
|
|
|
return "redirect:http://msb.auth.com/login.html";
|
|
|
|
|
}
|
|
|
|
|
// 说明获取Token信息成功
|
|
|
|
|
String json = EntityUtils.toString(post.getEntity());
|
|
|
|
|
SocialUser socialUser = JSON.parseObject(json, SocialUser.class);
|
|
|
|
|
R r = memberFeginService.socialLogin(socialUser);
|
|
|
|
|
if(r.getCode() != 0){
|
|
|
|
|
// 登录错误
|
|
|
|
|
return "redirect:http://msb.auth.com/login.html";
|
|
|
|
|
}
|
|
|
|
|
String entityJson = (String) r.get("entity");
|
|
|
|
|
System.out.println("----------------->" + entityJson);
|
|
|
|
|
// 注册成功就需要调整到商城的首页
|
|
|
|
|
return "redirect:http://msb.mall.com/home";
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 二、分布式session
|
|
|
|
|
|
|
|
|
|
## 1.session问题
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/5919a9909d4246cfa00d3851af823456.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/10a29ff1cd594db3aa7fc593e217dc35.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/654b5e4af3ff44dfabb6127daee5d225.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/27e2467140594f1bbe5b1e3a7075bc81.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/9916772823024deab38f500a28e8eec8.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/7e3963ba44814ea79db8ef376abe509c.png)
|
|
|
|
|
|
|
|
|
|
## 2.SpringSession整合
|
|
|
|
|
|
|
|
|
|
  我们通过SpringSession来实现Session的共享,Session数据存储在Redis中
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/7a07efc356b94ba1a21e2c646769fda8.png)
|
|
|
|
|
|
|
|
|
|
SpringSession的操作指南:
|
|
|
|
|
|
|
|
|
|
https://docs.spring.io/spring-session/docs/2.5.6/reference/html5/guides/boot-redis.html
|
|
|
|
|
|
|
|
|
|
导入相关的依赖
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.session</groupId>
|
|
|
|
|
<artifactId>spring-session-data-redis</artifactId>
|
|
|
|
|
</dependency>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
设置对应的配置
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/b3f81aef68744b5ea4f82bdce1e1ed44.png)
|
|
|
|
|
|
|
|
|
|
最后我们需要添加对有的注解,放开操作
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/821a371533ba42838cad825568db77f7.png)
|
|
|
|
|
|
|
|
|
|
然后在Auth服务和商城首页都整合SpringSession后,我们再商城首页可以看到Session的数据,注意这儿是手动修改Cookie的域名
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/a3b63318cee24cc889749026b5827f9b.png)
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/e902ee72dfa5419a9444b7840fbdfbfe.png)
|
|
|
|
|
|
|
|
|
|
## 3.自定义Cookie
|
|
|
|
|
|
|
|
|
|
  通过自定义Cookie实现session域名的调整
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
@Configuration
|
|
|
|
|
public class MySessionConfig {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 自定义Cookie的配置
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
@Bean
|
|
|
|
|
public CookieSerializer cookieSerializer(){
|
|
|
|
|
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
|
|
|
|
|
cookieSerializer.setDomainName("msb.com"); // 设置session对应的一级域名
|
|
|
|
|
cookieSerializer.setCookieName("msbsession");
|
|
|
|
|
return cookieSerializer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 对存储在Redis中的数据指定序列化的方式
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
@Bean
|
|
|
|
|
public RedisSerializer<Object> redisSerializer(){
|
|
|
|
|
return new GenericJackson2JsonRedisSerializer();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 4.单点登录案例演示
|
|
|
|
|
|
|
|
|
|
  xxl-sso案例代码地址:https://gitee.com/xuxueli0323/xxl-sso?_from=gitee_search
|
|
|
|
|
|
|
|
|
|
下载下来的代码解压缩后通过idea导入,然后修改server和simple中的属性文件,同时我们需要在host中设置对应的域名
|
|
|
|
|
|
|
|
|
|
```txt
|
|
|
|
|
127.0.0.1 ssoserver.com
|
|
|
|
|
127.0.0.1 msb1.com
|
|
|
|
|
127.0.0.1 msb2.com
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
在server的配置文件中,修改Redis的服务地址
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/56969019e13b4ad78cbabf2458bd9545.png)
|
|
|
|
|
|
|
|
|
|
然后在simple中修改server的地址和redis服务的地址
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/189eac1a373d4bc8935d36f5bab1d9e1.png)
|
|
|
|
|
|
|
|
|
|
然后分别启动服务测试即可
|
|
|
|
|
|
|
|
|
|
![image.png](https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1462/1650940644078/d13eacf0ffd44e74a56bf65aeb0dcc1f.png)
|