谷粒商城-认证服务

目录

商城业务-认证服务-环境搭建

商城业务-认证服务-好玩的验证码倒计时

商城业务-认证服务-整合短信验证码

商城业务-认证服务-验证码防刷校验

商城业务-认证服务-一步一坑的注册页环境

商城业务-认证服务-异常机制

商城业务-认证服务-MD5&盐值&BCrypt

商城业务-认证服务-注册完成

商城业务-认证服务-账号密码登录完成

商城业务-认证服务-OAuth2.0简介

商城业务-认证服务-weibo登录测试

商城业务-认证服务-社交登录回调

商城业务-认证服务-社交登录完成

商城业务-认证服务-社交登录测试成功

商城业务-认证服务-分布式session不共享不同步问题

商城业务-认证服务-分布式session解决方案原理

商城业务-认证服务-SpringSession整合

商城业务-认证服务-自定义SpringSession完成子域session共享

商城业务-认证服务-SpringSession原理

商城业务-认证服务-页面效果完成

商城业务-认证服务-单点登录简介

商城业务-认证服务-补-框架效果演示

商城业务-认证服务-单点登录流程-1

商城业务-认证服务-单点登录流程-2

商城业务-认证服务-单点登录流程-3


商城业务-认证服务-环境搭建

1.创建认证服务

①使用spring初始化向导创建服务

②选择SpringBoot的版本,添加服务需要的依赖

 需要注册中心和配置中心的依赖,因此,导入common,还需排除mybatis的依赖,因为不用数据库

2. 开启服务注册功能

①配置配置文件

②开启服务注册功能

Nginx动静分类 

①配置域名

②templates中导入登录、注册的html

将注册页面的index.html改名为reg.html,登录页面的html暂时不改名方便后面测试能否获取到Ngixn的静态资源,因为SpringMVC默认访问templates下的index.html,否则需要Controller路由

 

③上传静态资源至Nginx

 

④修改访问路径(CTRL+R)

 ⑤配置网关

商城业务-认证服务-好玩的验证码倒计时

1.编写路径跳转的Controller

如果编写一个接口仅仅是为了跳转页面,没有数据的处理,如果这样的跳转接口多了则可以使用SpringMVC的view Controller(视图控制器)将请求与页面进行绑定

2.为了页面修改能实时看到效果,关闭thymeleaf的缓存

3. 修改首页、注册页、登录页的正确跳转

①点击谷粒商城正确跳转首页

②点击立即注册跳转注册页面

③点击登录跳转登录页面、点击注册跳转注册页面

④点击请登录跳转登录页面

⑤点击谷粒商城跳转首页页面

4.倒计时60s的编写

①为sendCode绑定点击事件

出现问题:可以多次点击,多个事件会叠加在一起 

解决方案: 当被点击之后为class值添加disabled,判断class的值是否可点击

商城业务-认证服务-整合短信验证码

1.进入阿里云官网,点击云市场中的三网短信接口

地址:API市场-云市场-阿里云

2.购买0元体验

点击官方106三网短信

3. 在管理控制台中查看已购买的短信验证API

有各个参数的详细解释以及java的示例代码

 点击短信接口超链接,有详细的API接口文档

Host的获取即调用地址去除/sms/smsSend和(s)

AppCode的获取

AppCode的拼接方式

smsSignId公司的签名,这个需要自己跟客服去申请,就下图圈起来的东西

可以点击去调试按钮进行一个简单的使用体验

4.简单测试

输入你的appCode,HttpUtils按照注释自行下载

将复制的HttpUtils放在第三方服务的util包下,文件上传、短信验证、物流查询都属于第三方服务

5. 编写可配置的发送短信的接口

商城业务-认证服务-验证码防刷校验

1.编写短信验证controller,方便其它服务调用

2. 认证服务远程调用发送短信验证码功能

①依赖已导入,开启远程服务调用功能

② 远程调用接口编写

3.认证服务中编写获取短信验证码的controller

4. 注册页面编写请求发送验证码功能

①为手机号码input框设置id,方便获取

②发送请求,请求后台发送短信验证码

问题1:有人拿到请求路径恶意请求

解决方案:后续会说明

5.防止一个手机号码60s内多次获取短信验证码

解决思路:将短信验证码存储在redis中,key为phoneNum,value为验证码和存储时系统的当前时间。从redis中查询为null则调用发送短信验证码,若查询不为空则判断是否超过60s,是则再次调用发送短信验证码,否则返回提示信息。

①导入redis的依赖,并配置好redis

②common的constant中编写验证码前置

③编写错误代码

④接口编写


@RestController
public class LoginController {

    @Autowired
    private SmsSCFeignService smsSCFeignService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("/sms/sendcode")
    public R sendCode(@RequestParam("phone") String phone){
        // TODO 接口防刷
        // 处理一个手机号码60s内多次获取短信验证码问题
        String s = stringRedisTemplate.opsForValue().get(SmsConstant.SMS_CODE_CACHE_PREFIX + phone);
        if (StringUtils.isNotEmpty(s)){
            // 获取存储时的系统时间
            Long saveTime = Long.parseLong(s.split("_")[1]);
            // 单位为毫秒,因此,60秒要转化为毫秒即60000
            if (saveTime - System.currentTimeMillis()< 60000){
                return R.error(BizCodeEnum.SMS_CODE_EXPTION.getCode(), BizCodeEnum.SMS_CODE_EXPTION.getMsg());
            }
        }
        String code = UUID.randomUUID().toString().substring(0,5);
        stringRedisTemplate.opsForValue().set(SmsConstant.SMS_CODE_CACHE_PREFIX+phone,code+"_"+System.currentTimeMillis(),10, TimeUnit.MINUTES);
        smsSCFeignService.sendCode(phone,code);
        return R.ok();
    }

}

⑤ 注册页面的请求发送验证码的回调函数编写

商城业务-认证服务-一步一坑的注册页环境

1.编写注册接口

2.编写Vo封装注册数据

3. 使用JSR303进行数据校验

导入依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

 说明:不导入此依赖,@Valid注解不生效

使用@Valid注解开启数据校验功能,将校验后的结果封装到BindingResult中 

4.编写注册页面

 为每个input框设置name属性,值需要与Vo的属性名一一对应

点击注册按钮没有发送请求,说明:为注册按钮绑定了单击事件,禁止了默认行为。将绑定的单击事件注释掉 

 5.为Model绑定校验错误信息

方法一:

方法二: 

编写前端页面获取错误信息 

①导入thymeleaf的名称空间

② 封装错误信息

出现问题: 转发失败,打印字符串

出现问题的原因:controller层使用了@RestController注解会自动返回json数据

解决方案:使用@controller注解

出现问题: Request method 'POST' not supported

出现问题的原因:表单的提交使用的是post请求,会原封不动的转发给reg.html,但是/reg.html(路径映射默认都是get方式访问)

解决方案:如下图所示

出现问题:刷新页面,会重复提交表单

出现问题的原因:转发,原封不对转发过去

解决方案:使用重定向

出现问题:转发,数据都封装在Model中,而重定向获取不到 

解决方案:使用 RedirectAttributes

RedirectAttributes的方法讲解:Spring MVC ---- RedirectAttributes 使用,请求转发携带参数总结_zhangjian15的博客-CSDN博客

出现问题:重定向到服务端口地址 

解决方案: 写完整的域名路径

说明: RedirectAttributes的addFlashAttribute()方法是将errors保存在session中,刷新一次就没了

出现问题:分布式下重定向使用session存储数据会出现一些问题

解决方案:后续会说明

商城业务-认证服务-异常机制

1.校验验证码

2. 会员服务中编写Vo接受数据

3. 编写会员服务的用户注册接口

① 查询会员你得默认等级

② 检查用户名和手机号是否唯一

这里采用异常机制处理,如果查出用户名或密码不唯一则向上抛出异常

异常类的编写

检查用户名和手机号是否存在的方法编写

 

 

 如果抛出异常,则进行捕获

密码的设置,前端传来的密码是明文,存储到数据库中需要进行加密,后面会说到 

商城业务-认证服务-MD5&盐值&BCrypt

首先,加密分为可逆加密和不可逆加密。密码的加密为不可逆加密

什么是MD5?

 Apache.common下DigestUtils工具类的md5Hex()方法,将MD5加密后的数据转化为16进制

MD5并安全,很多在线网站都可以破解MD5,通过使用彩虹表,暴力破解。

因此,需要通过使用MD5+盐值进行加密 

盐值:随机生成的数

什么是加盐?

方法1是加默认盐值:$1$xxxxxxxx

方法2是加自定义盐值

缺点:还需额外在数据库中存储盐值

因此,可以使用Spring家的BCryptPasswordEncoder,它的encode()方法使用的就是MD5+盐值进行加密,盐值是随机产生的

通过matches()方法进行密码是否一致

用户注册业务中的密码加密

商城业务-认证服务-注册完成

1.在common的exception包下,编写异常枚举

2. 进行异常的捕获

3. 远程服务接口编写

4. 远程服务调用

5.注册页错误消息提示

商城业务-认证服务-账号密码登录完成

1.编写Vo

2.数据绑定

将ul包在表单里面

3. 编写登录接口

说明:不能加@RequestBody注解,这里是页面直接提交数据,数据类型是map并非json

4.member服务的Vo编写

5. member服务用户校验接口编写

 编写异常枚举

6.远程服务接口编写

7.错误信息提示 

商城业务-认证服务-OAuth2.0简介

 社交登录使用的是Auth2.0,Auth2.0的流程如下图所示:

商城业务-认证服务-weibo登录测试

1.搜索微博开放平台

地址:新浪微博开放平台-首页

找到微链接,点击网站接入

点击立即接入

填写应用名称

点击我的应用

 App Key 和 App Secret 是获取 Access token必填的参数

填写授权回调地址和授权失败回调地址

微博Auth2.0文档地址: 授权机制说明 - 微博API

2.将QQ样式修改为微博样式

3.请求用户授权 

https://api.weibo.com/oauth2/authorize?client_id=123050457758183&redirect_uri=http://www.example.com/response&response_type=code

授权成功会跳转成功页面并携带一个code码,可以根据这个code码获取Access token 

通过code获取Access token

 说明:

①code只能使用一次,Access token只能一段时间有效

②uuid唯一,和关联账户绑定

拿到Access token 可以获取微博开放用户的信息 ,例如用户的性别、年龄等

通过微博提供的用户信息查询接口查询用户信息

商城业务-认证服务-社交登录回调

授权认证的时序图

 1.修改授权成功回调页

 修改超链接中的回调地址

2. 将third-part服务下的utils包下的HttpUtils工具类复制到common中

3.编写controller专门处理社交登录请求 

出现问题:微博登录接入出现错误码21322(重定向地址不匹配)

 解决方案:微博登录接入出现错误码21322(重定向地址不匹配),其他解决方法_wwang_dev的博客-CSDN博客_21322 微博

清除缓存,重新测试即可

商城业务-认证服务-社交登录完成

 1. 编写获取Access token的实体类

 将获取到的json数据,利用json在线工具平台转化为java对象

 

getEntity()获取到json数据,将json数据转为字符串,将字符串转为java对象 

2. 为member表新增三个字段

增加新的属性

 

3.会员服务创建接口处理第一次社交登录

将认证服务的SocialUserVo拷贝到member服务的vo包下

商城业务-认证服务-社交登录测试成功

1.远程服务接口编写

2. 拷贝memberEntity的属性

3.远程服务调用

商城业务-认证服务-分布式session不共享不同步问题

登录成功后,NickName的显示

在之前的单体应用中,会将登录成功后的属性保存到session中 

Thymeleaf取出session 

出现问题:NickName未显示 

出现问题的原因:Session不能跨域使用

auth.gulimall域下的session作用域只限于auth.gulimall域,gulimall域是获取不到的,不共享的

session原理: 

分布式下session会出现问题如下:

①同一个服务,复制多份,session不同步问题

②不同服务,session不能共享问题

商城业务-认证服务-分布式session解决方案原理

方案一:sessio复制,不采用

方案二:客户端存储,不采用

方案三: 利用hash一致性,进行负载均衡,可以采用但是这里不采用

方案四: 统一存储,这里采用这套方案

SpringSession已经为我们做好了 

放大域名 ,SpringSession也为我们做好了

 

商城业务-认证服务-SpringSession整合

 

传送门: Spring Session - Spring Boot

SpringSession整合redis的使用步骤:

①整合依赖

	<dependency>
		<groupId>org.springframework.session</groupId>
		<artifactId>spring-session-data-redis</artifactId>
	</dependency>

② boot配置

spring.session.store-type=redis # Session store type

server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified,seconds is used
spring.session.redis.flush-mode=on_save # Sessions flush mode
spring.session.redis.namespace=spring:session # Namespace for keys used to store sessions

③redis连接配置

spring.redis.host=localhost # Redis server host
spring.redis.password= # Login password of the redis server
spring.redis.port=6379 # Redis server port

④Java配置

使用@EnableRedisHttpSession注解开启Spring Session with Redis功能

@EnableRedisHttpSession 
public class Config {

	@Bean
	public LettuceConnectionFactory connectionFactory() {
		return new LettuceConnectionFactory(); 
	}

}

1.Auth服务按照上列步骤完成Spring Session with Redis的整合

①整合依赖

② boot配置

③redis连接配置之前已经配置过了,略去

④Java配置

测试:看是否将session存入redis中

出现问题:DefaultSerializer requires a Serializable payload but received an object of type [com.atguigu.gulimall.auth.vo.MemberRespVo]

出现的原因: MemberRespVo未实现序列化解接口

解决方案:

保存成功,redis中有数据

 

2.Product服务按照上列步骤完成Spring Session with Redis的整合 

①导入依赖

②boot配置

③之前已配置过redis连接配置

④Java配置

3. 将MemberRespVo复制到commom中,因为,product服务还需要将Session中存储的loginUser反序列化为MemberRespVo对象

将redis中的session删除,因为,session中存储的loginUser类型为 auth服务vo包下的,需要存储common服务vo包下的类型

4. 手动修改session的作用域

 

商城业务-认证服务-自定义SpringSession完成子域session共享

解决子域session共享问题:

@Bean
	public CookieSerializer cookieSerializer() {
		DefaultCookieSerializer serializer = new DefaultCookieSerializer();
		serializer.setCookieName("JSESSIONID"); 
		serializer.setCookiePath("/"); 
		serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); 
		return serializer;
	}

解决使用json序列化方式来序列化对象数据到redis中

传送门:spring-session/SessionConfig.java at 2.4.6 · spring-projects/spring-session · GitHub

@Configuration
public class SessionConfig implements BeanClassLoaderAware {

	private ClassLoader loader;

	@Bean
	public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
		return new GenericJackson2JsonRedisSerializer(objectMapper());
	}
}

 

@Configuration
public class GulimallSessionConfig {
    /**
     * 子域问题共享解决
     */
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("gulimall.com");
        cookieSerializer.setCookieName("GULIMALLSESSION");
        return cookieSerializer;
    }

    /**
     * 使用json序列化方式来序列化对象数据到redis中
     */
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
       return new GenericJackson2JsonRedisSerializer();
    }
}

给product服务和auth服务各配置一份

前端页面修改,需要进行非空判断

将redis和客户端的session进行清空

商城业务-认证服务-SpringSession原理

@EnableRedisHttpSession注解导入了RedisHttpSessionConfiguration.class这个配置类

在 RedisHttpSessionConfiguration.class这个配置类,为容器中注入了一个组件

sessionRepository  ->  sessionRedisOperations : redis操作session,实现session的增删改查

 调用SpringHttpSessionConfiguration中的springSessionRepositoryFilter()方法,获取一个

 SessionRepositoryFilter对象,调用doFilterInternal()对原生的request和response对象进行封装即装饰者模式,request对象调用getSession()方法就会调用wrapperRequest对象的getSession()方法

商城业务-认证服务-页面效果完成

通过账号密码登录的用户信息也保存到session中

①编写一个可修改的属性key

② 用户信息也保存到session中

③设置默认的昵称

④ 登录后,首页页面细化

已经登录的话,在进入登录页要实现跳转首页的效果

①自己编写业务逻辑,将自动页面映射注释

②编写接口

商品详情页,用户昵称显示

 

搜索页,用户昵称显示

①导入依赖

 <!--导入Spring Session with redis 依赖-->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <!--导入SpringBoot整合Redis的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

 ②配置

③ 开启共享session功能

④ 复制配置类

⑤ 前端代码

商城业务-认证服务-单点登录简介

什么是单点登录?只要注册了登录某一个服务就可以自动登录其它所有服务,例如:注册登录了谷粒商城,则可以自动登录在线教育、众筹系统等

商城业务-认证服务-补-框架效果演示

1.码云搜索xxl,下载单点登录的开源框架

传送门:xxl-sso: 一个分布式单点登录框架。只需要登录一次就可以访问所有相互信任的应用系统。 拥有"轻量级、分布式、跨域、Cookie+Token均支持、Web+APP均支持"等特性;。现已开放源代码,开箱即用。

2.配置域名 

ssoserver.com 作为认证中心的域名,client1.com、client2.com分别作为客户端1和客户端2的域名

3. 修改认证中心和客户端的配置文件

4.进行打包

mvn clean package -Dmaven.skip.test=true

5.启动认证中心和客户端

 

认证中心访问路径:http://ssoserver.com:8080/xxl-sso-server
客户端1访问路径:http://client1.com:8081/xxl-sso-web-sample-springboot
客户端2访问路径:http://client2.com:8082/xxl-sso-web-sample-springboot

商城业务-认证服务-单点登录流程-1

单点登录的核心逻辑:

单点登录的第一步流程:

1.使用初始化向导创建认证中心和客户端服务

修改客户端服务的端口号 

2. 编写接口

配置认证中心的认证地址 

当认证中心认证完成之后,让认证中心知道你要跳转回的地址?解决方案就是在请求参数中携带跳转回的地址

编写list页面

3. 编写处理认证的请求

编写login页面 

商城业务-认证服务-单点登录流程-2

1.编写一个隐藏的input框,用于存储调回的url

2.导入redis的依赖,配置redis 

 

3. 登录成功保存用户信息并传递token

4. 拿到令牌需要去认证中心查询用户的信息,这里只是简单保存了以下并没有模拟 

商城业务-认证服务-单点登录流程-3

1.认证中心编写接口查询用户信息

2.去认证中心查询用户信息

3.复制client服务,并修改端口、服务名等信息

 

 

 4.实现一次登录,处处登录的核心就是认证通过之后给浏览器留下一个痕迹,凡是访ssoserver.com这个域名的都会带上这个痕迹,通过使用cookie实现

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值