写在开局 : 本篇文章 和 美食社交的认证授权中心同步, 实现简单功能:
[用户登录与注册], 同时附上认证授权的文章地址:认证授权文章链接

1. 发送验证码

1.2 Redis 配置类

package com.itkaka.diners.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisTemplateConfiguration {/*** redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类** @param redisConnectionFactory* @return*/@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);// 使用Jackson2JsonRedisSerialize 替换默认序列化Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper objectMapper = new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);jackson2JsonRedisSerializer.setObjectMapper(objectMapper);// 设置key和value的序列化规则redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();return redisTemplate;}}

1.3 公共枚举类

package com.itkaka.commons.constant;import lombok.Getter;@Getter
public enum RedisKeyConstant {verify_code("verify_code:", "验证码"),private String key;private String desc;RedisKeyConstant(String key, String desc) {this.key = key;this.desc = desc;}}

1.4 Service业务层代码

package com.itkaka.diners.service;import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.itkaka.commons.constant.RedisKeyConstant;
import com.itkaka.commons.utils.AssertUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;/*** 发送验证码业务逻辑层*/
@Service
public class SendVerifyCodeService {@Resourceprivate RedisTemplate<String, String> redisTemplate;/*** 发送验证码** @param phone*/public void send(String phone) {// 检查非空AssertUtil.isNotEmpty(phone, "手机号不能为空");// 根据手机号查询是否已生成验证码,已生成直接返回if (!checkCodeIsExpired(phone)) {return;}// 生成 6 位验证码String code = RandomUtil.randomNumbers(6);// 调用短信服务发送短信(忽略)// 发送成功,将 code 保存到 Redis,失效时间 60sString key = RedisKeyConstant.verify_code.getKey() + phone;redisTemplate.opsForValue().set(key, code, 60, TimeUnit.SECONDS);}/*** 根据手机号查询是否已生成验证码** @param phone* @return*/private boolean checkCodeIsExpired(String phone) {String key = RedisKeyConstant.verify_code.getKey() + phone;String code = redisTemplate.opsForValue().get(key);return StrUtil.isBlank(code) ? true : false;}/*** 根据手机号获取验证码** @param phone* @return*/public String getCodeByPhone(String phone) {String key = RedisKeyConstant.verify_code.getKey() + phone;return redisTemplate.opsForValue().get(key);}}

1.5 Controller控制层代码

package com.itkaka.diners.controller;import com.itkaka.commons.model.domain.ResultInfo;
import com.itkaka.commons.utils.ResultInfoUtil;
import com.itkaka.diners.service.SendVerifyCodeService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;/*** 发送验证码控制层*/
@RestController
public class SendVerifyCodeController {@Resourceprivate HttpServletRequest request;@Resourceprivate SendVerifyCodeService sendVerifyCodeService;/*** 发送验证码** @param phone* @return*/@GetMapping("send")public ResultInfo<String> send(String phone) {sendVerifyCodeService.send(phone);return ResultInfoUtil.buildSuccess("发送成功", request.getServletPath());}}

1.6 网关设置

白名单放行发送验证码接口

server:port: 80 # 端口spring:application:name: fs_gateway # 应用名cloud:gateway:discovery:locator:enabled: true # 开启配置注册中心进行路由功能lower-case-service-id: true # 将服务名称转小写routes:- id: fs_dinersuri: lb://fs_dinerspredicates:- Path=/diners/**filters:- StripPrefix=1- id: fs_oauthuri: lb://fs_oauthpredicates:- Path=/auth/**filters:- StripPrefix=1secure:ignore:urls: # 配置白名单路径- /actuator/**- /auth/oauth/**- /diners/signin- /diners/send# 配置 Eureka Server 注册中心
eureka:instance:# 开启 ip 注册prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${server.port}client:service-url:defaultZone: http://localhost:8090/eureka/# 配置日志
logging:pattern:console: '%d{2100-01-01 13:14:00.666} [%thread] %-5level %logger{50} - %msg%n'

1.7 测试

访问:http://localhost/diners/send?phone=12311112222
返回结果:

{"code": 1,"message": "Successful.","path": "发送成功","data": "/send"
}

2. 注册

2.1 是否已注册

2.1.1 Mapper持久层
package com.itkaka.diners.mapper;import com.itkaka.commons.model.dto.DinersDTO;
import com.itkaka.commons.model.pojo.Diners;
import com.itkaka.commons.model.vo.ShortDinerInfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;import java.util.List;/*** 食客 Mapper*/
public interface DinersMapper {/*** 根据手机号查询食客信息** @param phone* @return*/@Select("select id, username, phone, email, is_valid " +" from t_diners where phone = #{phone}")Diners selectByPhone(@Param("phone") String phone);/*** 根据用户名查询食客信息** @param username* @return*/@Select("select id, username, phone, email, is_valid " +" from t_diners where username = #{username}")Diners selectByUsername(@Param("username") String username);/*** 新增食客信息** @param dinersDTO* @return*/@Insert("insert into " +" t_diners (username, password, phone, roles, is_valid, create_date, update_date) " +" values (#{username}, #{password}, #{phone}, \"ROLE_USER\", 1, now(), now())")int save(DinersDTO dinersDTO);/*** 根据 ID 集合查询食客信息** @param ids* @return*/@Select("<script> " +" select id, nickname, avatar_url from t_diners " +" where is_valid = 1 and id in " +" <foreach item='id' collection='ids' open='(' separator=',' close=')'> " +" #{id} " +" </foreach> " +" </script>")List<ShortDinerInfo> findByIds(@Param("ids") String[] ids);}
2.1.2 Service
package com.itkaka.diners.service;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.itkaka.commons.constant.ApiConstant;
import com.itkaka.commons.model.domain.ResultInfo;
import com.itkaka.commons.model.dto.DinersDTO;
import com.itkaka.commons.model.pojo.Diners;
import com.itkaka.commons.model.vo.ShortDinerInfo;
import com.itkaka.commons.utils.AssertUtil;
import com.itkaka.commons.utils.ResultInfoUtil;
import com.itkaka.diners.config.OAuthClientConfiguration;
import com.itkaka.diners.config.OAuthClientConfiguration;
import com.itkaka.diners.mapper.DinersMapper;
import com.itkaka.diners.model.domain.OAuthDinerInfo;
import com.itkaka.diners.model.vo.LoginDinerInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;/*** 食客服务业务逻辑层*/
@Service
public class DinersService {@Resourceprivate RestTemplate restTemplate;@Value("${service.name.fs_oauth-server}")private String oauthServerName;@Resourceprivate OAuthClientConfiguration oAuthClientConfiguration;@Resourceprivate DinersMapper dinersMapper;@Resourceprivate com.itkaka.diners.service.SendVerifyCodeService sendVerifyCodeService;/*** 登录** @param account  账号信息:用户名或手机或邮箱* @param password 密码* @param path     请求路径* @return*/public ResultInfo signIn(String account, String password, String path) {// 参数校验AssertUtil.isNotEmpty(account, "请输入登录账户");AssertUtil.isNotEmpty(password, "请输入登录密码");// 构建请求头HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);// 构建请求体MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();body.add("username", account);body.add("password", password);body.setAll(BeanUtil.beanToMap(oAuthClientConfiguration));// 设置AuthorizationHttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);// 设置BasicAuthorizationrestTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(oAuthClientConfiguration.getClientId(),oAuthClientConfiguration.getSecret()));// 发送请求ResponseEntity<ResultInfo> result = restTemplate.postForEntity(oauthServerName + "oauth/token",entity, ResultInfo.class);// 处理返回结果AssertUtil.isTrue(result.getStatusCode() != HttpStatus.OK, "登录失败!");ResultInfo resultInfo = result.getBody();if (resultInfo.getCode() != ApiConstant.SUCCESS_CODE) {// 登录失败resultInfo.setData(resultInfo.getMessage());return resultInfo;}OAuthDinerInfo dinerInfo = BeanUtil.fillBeanWithMap((LinkedHashMap) resultInfo.getData(),new OAuthDinerInfo(), false);LoginDinerInfo loginDinerInfo = new LoginDinerInfo();loginDinerInfo.setToken(dinerInfo.getAccessToken());loginDinerInfo.setNickname(dinerInfo.getNickname());loginDinerInfo.setAvatarUrl(dinerInfo.getAvatarUrl());return ResultInfoUtil.buildSuccess(path, loginDinerInfo);}/*** 校验手机号是否已注册** @param phone*/public void checkPhoneIsRegistered(String phone) {AssertUtil.isNotEmpty(phone, "手机号不能为空");Diners diners = dinersMapper.selectByPhone(phone);AssertUtil.isTrue(diners == null, "该手机号未注册");AssertUtil.isTrue(diners.getIsValid() == 0, "该用户已锁定,请先解锁");}/*** 用户注册** @param dinersDTO* @param path* @return*/public ResultInfo register(DinersDTO dinersDTO, String path) {// 参数非空校验String username = dinersDTO.getUsername();AssertUtil.isNotEmpty(username, "请输入用户名");String password = dinersDTO.getPassword();AssertUtil.isNotEmpty(username, "请输入密码");String phone = dinersDTO.getPhone();AssertUtil.isNotEmpty(username, "请输入手机号");String verifyCode = dinersDTO.getVerifyCode();AssertUtil.isNotEmpty(username, "请输入验证码");// 获取验证码String code = sendVerifyCodeService.getCodeByPhone(phone);// 验证码是否已过期AssertUtil.isNotEmpty(code, "验证码已过期,请重新发送");// 校验验证码一致性AssertUtil.isTrue(!dinersDTO.getVerifyCode().equals(code),"验证码不一致,请重新输入");// 验证用户名是否已注册Diners diners = dinersMapper.selectByUsername(username.trim());AssertUtil.isTrue(diners != null, "用户名已存在,请重新输入");// 注册// 密码加密dinersDTO.setPassword(DigestUtil.md5Hex(password.trim()));dinersMapper.save(dinersDTO);// 自动登录return signIn(username.trim(), password.trim(), path);}/*** 根据食客 ID 集合查询食客信息** @param ids 主键 id 集合,多个以逗号分隔,逗号之间不用空格* @return*/public List<ShortDinerInfo> findByIds(String ids) {AssertUtil.isNotEmpty(ids);String[] idArr = ids.split(",");List<ShortDinerInfo> dinerInfos = dinersMapper.findByIds(idArr);return dinerInfos;}}
2.1.3 Controller
package com.itkaka.diners.controller;import com.itkaka.commons.model.domain.ResultInfo;
import com.itkaka.commons.model.dto.DinersDTO;
import com.itkaka.commons.model.vo.ShortDinerInfo;
import com.itkaka.commons.utils.ResultInfoUtil;
import com.itkaka.diners.service.DinersService;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;/*** 食客服务控制层*/
@RestController
@Api(tags = "食客相关接口")
public class DinersController {@Resourceprivate DinersService dinersService;@Resourceprivate HttpServletRequest request;/*** 登录** @param account* @param password* @return*/@GetMapping("signin")public ResultInfo signIn(String account, String password) {return dinersService.signIn(account, password, request.getServletPath());}/*** 校验手机号是否已注册** @param phone* @return*/@GetMapping("checkPhone")public ResultInfo checkPhone(String phone) {dinersService.checkPhoneIsRegistered(phone);return ResultInfoUtil.buildSuccess(request.getServletPath());}/*** 用户注册** @param dinersDTO* @return*/@PostMapping("register")public ResultInfo register(@RequestBody DinersDTO dinersDTO) {return dinersService.register(dinersDTO, request.getServletPath());}/*** 根据食客 ID 集合查询食客信息** @param ids 主键 id 集合,多个以逗号分隔,逗号之间不用空格* @return*/@GetMapping("findByIds")public ResultInfo<List<ShortDinerInfo>> findByIds(String ids) {List<ShortDinerInfo> dinerInfos = dinersService.findByIds(ids);return ResultInfoUtil.buildSuccess(request.getServletPath(), dinerInfos);}}
2.1.4 网关配置

放行校验手机号接口

secure:
ignore:urls: # 配置白名单路径- /actuator/**- /auth/oauth/**- /diners/signin- /diners/send- /diners/checkPhone

测试
访问:http://localhost/diners/checkPhone?phone=12311112222
返回结果(已注册):

{"code": 1,"message": "Successful.","path": "/checkPhone","data": null
}

返回结果 (未注册)

{"timestamp": "2020-11-15T10:16:23.815+00:00","status": 500,"error": "Internal Server Error","message": "","path": "/checkPhone"
}

2.2 全局异常处理

package com.itkaka.diners.handler;import com.itkaka.commons.exception.ParameterException;
import com.itkaka.commons.model.domain.ResultInfo;
import com.itkaka.commons.utils.ResultInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;@RestControllerAdvice // 将输出的内容写入 ResponseBody 中
@Slf4j
public class GlobalExceptionHandler {@Resourceprivate HttpServletRequest request;@ExceptionHandler(ParameterException.class)public ResultInfo<Map<String, String>> handlerParameterException(ParameterException ex) {String path = request.getRequestURI();ResultInfo<Map<String, String>> resultInfo =ResultInfoUtil.buildError(ex.getErrorCode(), ex.getMessage(), path);return resultInfo;}@ExceptionHandler(Exception.class)public ResultInfo<Map<String, String>> handlerException(Exception ex) {log.info("未知异常:{}", ex);String path = request.getRequestURI();ResultInfo<Map<String, String>> resultInfo = ResultInfoUtil.buildError(path);return resultInfo;}}

测试

{"code": 0,"message": "该手机号未注册","path": "/checkPhone","data": null
}

2.3 完成注册

2.3.1 DTO (数据传输对象)
package com.itkaka.commons.model.dto;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;import java.io.Serializable;@Getter
@Setter
@ApiModel(description = "注册用户信息")
public class DinersDTO implements Serializable {@ApiModelProperty("用户名")private String username;@ApiModelProperty("密码")private String password;@ApiModelProperty("手机号")private String phone;@ApiModelProperty("验证码")private String verifyCode;}
2.3.2 Mapper
/*** 根据用户名查询食客信息*/@Select("select id, username, phone, email, is_valid " +" from t_diners where username = #{username}")Diners selectByUsername(@Param("username") String username);/*** 新增食客信息*/@Insert("insert into " +" t_diners (username, password, phone, roles, is_valid, create_date, update_date) " +" values (#{username}, #{password}, #{phone}, \"ROLE_USER\", 1, now(), now())")int save(DinersDTO dinersDTO);
2.3.3 Service

SendVerifyCodeService.java

package com.itkaka.diners.service;import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.itkaka.commons.constant.RedisKeyConstant;
import com.itkaka.commons.utils.AssertUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;/*** 发送验证码业务逻辑层*/
@Service
public class SendVerifyCodeService {@Resourceprivate RedisTemplate<String, String> redisTemplate;/*** 发送验证码** @param phone*/public void send(String phone) {// 检查非空AssertUtil.isNotEmpty(phone, "手机号不能为空");// 根据手机号查询是否已生成验证码,已生成直接返回if (!checkCodeIsExpired(phone)) {return;}// 生成 6 位验证码String code = RandomUtil.randomNumbers(6);// 调用短信服务发送短信(忽略)// 发送成功,将 code 保存到 Redis,失效时间 60sString key = RedisKeyConstant.verify_code.getKey() + phone;redisTemplate.opsForValue().set(key, code, 60, TimeUnit.SECONDS);}/*** 根据手机号查询是否已生成验证码** @param phone* @return*/private boolean checkCodeIsExpired(String phone) {String key = RedisKeyConstant.verify_code.getKey() + phone;String code = redisTemplate.opsForValue().get(key);return StrUtil.isBlank(code) ? true : false;}/*** 根据手机号获取验证码** @param phone* @return*/public String getCodeByPhone(String phone) {String key = RedisKeyConstant.verify_code.getKey() + phone;return redisTemplate.opsForValue().get(key);}}

DinersService.java

package com.itkaka.diners.service;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.itkaka.commons.constant.ApiConstant;
import com.itkaka.commons.model.domain.ResultInfo;
import com.itkaka.commons.model.dto.DinersDTO;
import com.itkaka.commons.model.pojo.Diners;
import com.itkaka.commons.model.vo.ShortDinerInfo;
import com.itkaka.commons.utils.AssertUtil;
import com.itkaka.commons.utils.ResultInfoUtil;
import com.itkaka.diners.config.OAuthClientConfiguration;
import com.itkaka.diners.config.OAuthClientConfiguration;
import com.itkaka.diners.mapper.DinersMapper;
import com.itkaka.diners.model.domain.OAuthDinerInfo;
import com.itkaka.diners.model.vo.LoginDinerInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;/*** 食客服务业务逻辑层*/
@Service
public class DinersService {@Resourceprivate RestTemplate restTemplate;@Value("${service.name.fs_oauth-server}")private String oauthServerName;@Resourceprivate OAuthClientConfiguration oAuthClientConfiguration;@Resourceprivate DinersMapper dinersMapper;@Resourceprivate com.itkaka.diners.service.SendVerifyCodeService sendVerifyCodeService;/*** 登录** @param account  账号信息:用户名或手机或邮箱* @param password 密码* @param path     请求路径* @return*/public ResultInfo signIn(String account, String password, String path) {// 参数校验AssertUtil.isNotEmpty(account, "请输入登录账户");AssertUtil.isNotEmpty(password, "请输入登录密码");// 构建请求头HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);// 构建请求体MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();body.add("username", account);body.add("password", password);body.setAll(BeanUtil.beanToMap(oAuthClientConfiguration));// 设置AuthorizationHttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);// 设置BasicAuthorizationrestTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(oAuthClientConfiguration.getClientId(),oAuthClientConfiguration.getSecret()));// 发送请求ResponseEntity<ResultInfo> result = restTemplate.postForEntity(oauthServerName + "oauth/token",entity, ResultInfo.class);// 处理返回结果AssertUtil.isTrue(result.getStatusCode() != HttpStatus.OK, "登录失败!");ResultInfo resultInfo = result.getBody();if (resultInfo.getCode() != ApiConstant.SUCCESS_CODE) {// 登录失败resultInfo.setData(resultInfo.getMessage());return resultInfo;}OAuthDinerInfo dinerInfo = BeanUtil.fillBeanWithMap((LinkedHashMap) resultInfo.getData(),new OAuthDinerInfo(), false);LoginDinerInfo loginDinerInfo = new LoginDinerInfo();loginDinerInfo.setToken(dinerInfo.getAccessToken());loginDinerInfo.setNickname(dinerInfo.getNickname());loginDinerInfo.setAvatarUrl(dinerInfo.getAvatarUrl());return ResultInfoUtil.buildSuccess(path, loginDinerInfo);}/*** 校验手机号是否已注册** @param phone*/public void checkPhoneIsRegistered(String phone) {AssertUtil.isNotEmpty(phone, "手机号不能为空");Diners diners = dinersMapper.selectByPhone(phone);AssertUtil.isTrue(diners == null, "该手机号未注册");AssertUtil.isTrue(diners.getIsValid() == 0, "该用户已锁定,请先解锁");}/*** 用户注册** @param dinersDTO* @param path* @return*/public ResultInfo register(DinersDTO dinersDTO, String path) {// 参数非空校验String username = dinersDTO.getUsername();AssertUtil.isNotEmpty(username, "请输入用户名");String password = dinersDTO.getPassword();AssertUtil.isNotEmpty(username, "请输入密码");String phone = dinersDTO.getPhone();AssertUtil.isNotEmpty(username, "请输入手机号");String verifyCode = dinersDTO.getVerifyCode();AssertUtil.isNotEmpty(username, "请输入验证码");// 获取验证码String code = sendVerifyCodeService.getCodeByPhone(phone);// 验证码是否已过期AssertUtil.isNotEmpty(code, "验证码已过期,请重新发送");// 校验验证码一致性AssertUtil.isTrue(!dinersDTO.getVerifyCode().equals(code),"验证码不一致,请重新输入");// 验证用户名是否已注册Diners diners = dinersMapper.selectByUsername(username.trim());AssertUtil.isTrue(diners != null, "用户名已存在,请重新输入");// 注册// 密码加密dinersDTO.setPassword(DigestUtil.md5Hex(password.trim()));dinersMapper.save(dinersDTO);// 自动登录return signIn(username.trim(), password.trim(), path);}/*** 根据食客 ID 集合查询食客信息** @param ids 主键 id 集合,多个以逗号分隔,逗号之间不用空格* @return*/public List<ShortDinerInfo> findByIds(String ids) {AssertUtil.isNotEmpty(ids);String[] idArr = ids.split(",");List<ShortDinerInfo> dinerInfos = dinersMapper.findByIds(idArr);return dinerInfos;}}
2.3.4 Controller
   /*** 用户注册** @param dinersDTO* @return*/@PostMapping("register")public ResultInfo register(@RequestBody DinersDTO dinersDTO) {return dinersService.register(dinersDTO, request.getServletPath());}
2.3.5 网关配置

放行注册接口

secure:
ignore:urls: # 配置白名单路径- /actuator/**- /auth/oauth/**- /diners/signin- /diners/send- /diners/checkPhone- /diners/register
2.3.6 测试

先访问:http://localhost/diners/checkPhone?phone=12311113333
返回结果:

{"code": 0,"message": "该手机号未注册","path": "/checkPhone","data": null}

再访问:http://localhost/diners/send?phone=12311113333
返回结果(Redis 查看验证码):

{"code": 1,"message": "Successful.","path": "发送成功","data": "/send"
}

再访问:http://localhost/diners/register
请求参数:

{"username": "zhangsan","password": "123456","phone": "12311113333","verifyCode": "833275"
}

返回结果:

{"code": 1,"message": "Successful.","path": "/register","data": {"nickname": null,"token": "4323c187-5ffa-4e45-a3a3-e7cdff32145d","avatarUrl": null}
}



这是用户登录注册流程图,该图借鉴来源: 哈喽沃德先生的主页 -->哈喽沃德先生主页 ,可以在CSDN,知乎等平台搜索即可;

美食社交APP项目--用户注册相关推荐

  1. android app 的后台代码,包括后台的Android美食APP项目开源代码

    项目简介 小食光定位为一款集美食,社交,LBS服务于一体的美食推荐APP.为你发现周边美食的同时提供一个吃货分享的平台. APP截图 功能模块 美食推荐 :提供基础的美食信息查询: 商家推荐 : 基于 ...

  2. 魔方APP项目-04-用户模块API接口、Marshmallow,基本构造器(Schema),Schema数据序列化、Schema数据反序列化、反序列化对数据验证、模型构造器(ModelSchema)

    用户模块 当前开发的项目属于社交类型项目,所以关于用户的信息和功能直接贯穿了整个项目.所以此处实现用户模块功能,我们先把用户基本信息构建起来,并通过基本信息实现用户注册登录相关功能,后面遇到业务再继续 ...

  3. 让HR眼前一亮:30个APP项目软件测试经验,点燃你的简历

    在求职过程中,我们都希望自己的简历能够吸引面试官的眼球,从而获得更多的面试机会.作为一名软件测试人员,丰富的实战经验是让自己脱颖而出的关键之一. 在我多年从事APP项目软件测试的工作中,我积累了大量的 ...

  4. 社交app如何做好验证码防护不被刷

    社交是时代的主题.大众的生活需求正在改变.各种垂直社交APP接连不断.陌生社交的成功使社交网络服务APP燃烧,面对庞大的网络市场,社交产品几乎成为所有网民日常生活中不可缺少的应用程序. 网站或者APP ...

  5. JAVA社交平台项目第三天 即时通讯和接口加密

    第3章 - 即时通讯和接口加密 学习目标: 了解即时通讯业务场景和需求: 了解短连接和长连接 了解websocket协议 使用环信im云实现十次方即时通讯功能 了解接口加密业务需求 掌握常用加密算法和 ...

  6. App项目实战之路(二):API篇

    原创文章,转载请注明:转载自Keegan小钢 并标明原文链接:http://keeganlee.me/post/practice/20160812 微信订阅号:keeganlee_me 写于2016- ...

  7. 软件开发规范和标准_社交APP,社交直播软件开发怎样才可靠了?

    在网络飞速发展的今天,开发社交直播APP软件已经成为商家发展的必然,他们都需要社交直播APP或者小程序软件来拓展业务.那么社交APP,社交直播软件开发怎样才可靠了? 首先,甄别网络虚假宣传. 目前,傍 ...

  8. 轻量社交APP系统ThinkSNS 简 权威发布 限时惠购

    2019独角兽企业重金招聘Python工程师标准>>> 伴随国内外创业风潮.AI.区块链等互联网软件科技领域的高速发展,2019年,ThinkSNS软件品牌迎来十周年后的新纪元.作为 ...

  9. 某社交 App 涉黄被下架,真相令人窒息

    最近见识了一个令人窒息的事情. 某社交 App,为了让另一个竞品 App 下架,跑去竞品 App 平台下发布涉黄信息,自己进行截图举报. 其中,一个是 Soul,另一个是 Uki,双方都主打匿名声音社 ...

最新文章

  1. 程序猿,凭什么让你拿二十万
  2. 浅谈进程同步和互斥的概念
  3. 笔记 - AliCloud CDN 分发网络简介
  4. layui时间日期控件使用
  5. 阿里巴巴AI智能专场:整理分享
  6. Leetcode-MySQL-180. 连续出现的数字
  7. 如何安装oracle数据库
  8. mybatis map里面传对象_关于 MyBatis,我死磕了 10 种超好用的写法
  9. 报告显示:数据屏蔽降低业务安全风险
  10. 什么是servlet?servlet有什么用?
  11. 打造前端 Deepin Linux 工作环境——安装 nodejs 环境,git 版本管理
  12. 1357:车厢调度(train)
  13. python情绪识别_使用百度对话情绪识别api分析文本
  14. matlab gram schmidt,如何在 MATLAB 中用 行代码实现 Gram-Schmidt 正交化
  15. unity 转向和角度
  16. 敲简单前端小游戏——贪吃蛇
  17. 【ShaderToy】基础篇之谈谈点、线的绘制
  18. Alextnet网络
  19. linux实训项目——飞鸽(一)
  20. Git的基本概念和SourceTree的使用

热门文章

  1. 【微信小程序】微信小程序跳转H5页面的实现思路与方案
  2. css动画放大延迟,css3延时动画
  3. 22.11.14补卡 mysql学习笔记
  4. 人工智能商业应用,并介绍详细公司案列
  5. JS基于原型链的继承和基于类的继承学习总结
  6. 树莓派4b更换清华源
  7. PHP 函数的带问好的参数
  8. 上海线下沙龙|与专家面对面,畅聊如何打造高效能研发团队
  9. 跨境电商erp全套搭建教程(后端+移动端+网页版)
  10. Sublime中json美化插件的安装