一、首先创建一个新的服务zidanmall-auth-server
端口为:20000
1、pom.xml:
<dependencies> <dependency> <groupId>com.jiguiquan.zidanmall</groupId> <artifactId>zidanmall-common</artifactId> <version>1.0-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.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
2、配置文件 bootstrap.yml:
server: port: 20000 spring: application: name: zidanmall-auth-server cloud: nacos: discovery: server-addr: localhost:8848 config: server-addr: localhost:8848 file-extension: yaml namespace: 5eb1b2f2-6e86-4929-bb22-86a7119c1f7d group: dev
3、增加认证服务的DNS域名解析
我们到现在已经在host文件中添加了4个本地域名解析了
192.168.174.141 zidanmall.com 192.168.174.141 search.zidanmall.com 192.168.174.141 item.zidanmall.com 192.168.174.141 auth.zidanmall.com
注意,修改host后不重启机器,刷新DNS的方式:ipconfig /flushdns
4、配置nginx上的 *.zidamll.com 代理到网关规则和静态文件 /static/ 规则 —— 以前章节已配置
5、配置gateway网关:
- id: zidanmall_auth_route uri: lb://zidanmall-auth-server predicates: - Host=auth.zidanmall.com
6、添加login.html和reg.html两个登录、注册页面
7、关闭开发期间的thymeleaf的缓存 application.yml:
spring: thymeleaf: cache: false #开发期间关闭缓存功能,否则修改文件没有效果
配置完成后登录页面如下:

切换到注册页面:

二、完成注册页面的发送验证码功能
1、首先完成前端页面的点击动态倒计时效果,主要就是js效果:
$(function () {
   $("#sendCode").click(function () {
      //倒计时
      //给指定手机号发送验证码
      if ($(this).hasClass("disabled")) {  //在倒计时期间,不可用
         //正在倒计时
      } else {
         //发送验证码
         $.get("/sms/sendcode?phone=" + $("#phoneNum").val(), function (data) {
            if (data.code != 0) {
               alert(data.msg);
            }
         });
         timeoutChangeStyle();
      }
   });
})
var num = 10;
function timeoutChangeStyle() {
   $("#sendCode").attr("class", "disabled");
   if (num == 0) {
      $("#sendCode").text("发送验证码")
      num = 10;
      $("#sendCode").attr("class", "");
   } else {
      var str = num + "s后可再次发送";
      $("#sendCode").text(str)
      setTimeout("timeoutChangeStyle()", 1000);
   }
   num--;
}
2、html部分,就是个a标签:
<a id="sendCode"> 发送验证码 </a>
三、使用aliyun云市场—短信服务
1、当我们在云市场,购买了短信服务后,在商品的下方会有很详细的使用教程:

2、我们在第三方服务zidanmall-third-party中添加发送短信接口:
SMSService.java:
@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms")
@Data
@Service
public class SMSService {
    private String host;
    private String path;
    private String appcode;
    public void sendSMSCode(String phone, String code) {
        String method = "GET";
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Authorization", "APPCODE " + appcode);
        Map<String, String> querys = new HashMap<String, String>();
        querys.put("content", "【云通知】您的验证码是"+ code +"。如非本人操作,请忽略本短信");
        querys.put("mobile", phone);
        try {
            HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
            System.out.println(response.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
SMSController.java:
@RestController
@RequestMapping("/sms")
public class SMSController {
    @Autowired
    private SMSService smsService;
    @GetMapping("/sendCode")
    public R sendSmsCode(@RequestParam("phone") String phone, @RequestParam("code") String code){
        smsService.sendSMSCode(phone, code);
        return R.ok();
    }
}
其中用到的HttpUtils地址,文档也有说明:
3、在 zidanmall-auth-server 服务,使用Feign进行调用:
ThirdPartyFeignService.java:
@FeignClient(value = "zidanmall-third-party")
public interface ThirdPartyFeignService {
    @GetMapping("/sms/sendCode")
    R sendSmsCode(@RequestParam("phone") String phone, @RequestParam("code") String code);
}
LoginController.java:
@Controller
public class LoginController {
    @Autowired
    ThirdPartyFeignService thirdPartyFeignService;
    @Autowired
    StringRedisTemplate redisTemplate;
    @GetMapping("/sms/sendcode")
    @ResponseBody
    public R sendCode(@RequestParam("phone") String phone) {
        //TODO 接口防刷
        String redisCode = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        if (!StringUtils.isEmpty(redisCode)) {
            long saveTime = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - saveTime < 60 * 1000) {
                //60秒内 不能再发(防刷关键)
                return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMsg());
            }
        }
        //验证码再次校验 redis保存 key->phone value->code  sms:code:13812345678 - 4561
        String code = UUID.randomUUID().toString().substring(0, 5);
        String redisStorage =code+"_"+System.currentTimeMillis();
        //redis 缓存验证码 10分钟  防止同一phone 在60秒内再次发送
        redisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX+phone,redisStorage,10, TimeUnit.MINUTES);
        thirdPartyFeignService.sendSmsCode(phone,code);
        return R.ok();
    }
}
4、进行测试,页面点击发送验证码:

连续再发一条试试(60秒内)

说明我们的“短信防刷功能”可以工作!
四、通过配置,完成简单页面的跳转(WebMvcConfigurer.addViewControllers())
因为有些页面在跳转的过程中,不需要做任何业务操作,我们每次还得为其写一个Controller方法,只为进行跳转;
这样简单的工作我们可以直接使用配置完成:
@Configuration
public class ZidanmallWebConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login.html").setViewName("index");
        registry.addViewController("reg.html").setViewName("reg");
    }
}
五、完成



