总览:
在api模块下的service包,补充用户接口(UserService):用户登录
package com.bjpowernode.api.service;
import com.bjpowernode.api.model.User;
import com.bjpowernode.api.pojo.UserAccountInfo;
public interface UserService {
/**
* 根据手机号查询数据
*/
User queryByPhone(String phone);
/*用户注册*/
int userRegister(String phone, String password);
/*用户登录*/
User userLogin(String phone, String pword);
/*更新实名认证信息*/
boolean modifyRealname(String phone, String name, String idCard);
/*获取用户和资金信息*/
UserAccountInfo queryUserAllInfo(Integer uid);
/*查询用户*/
User queryById(Integer uid);
}
实现这个接口方法,在dataservice模块service包下,补充UserServiceImpl,用户登录:
1、检查参数(电话是否标准,密码是否标准)
2、md5密码加密
3、创建登录查询方法,是否该用户(编写相应的mapper)
4、更新最后登录时间(先判断是否存在用户)
5、返回用户对象
package com.bjpowernode.dataservice.service;
import com.bjpowernode.api.model.FinanceAccount;
import com.bjpowernode.api.model.User;
import com.bjpowernode.api.pojo.UserAccountInfo;
import com.bjpowernode.api.service.UserService;
import com.bjpowernode.common.util.CommonUtil;
import com.bjpowernode.dataservice.mapper.FinanceAccountMapper;
import com.bjpowernode.dataservice.mapper.UserMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
@DubboService(interfaceClass = UserService.class,version = "1.0")
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private FinanceAccountMapper financeAccountMapper;
@Value("${ylb.config.password-salt}")
private String passwordSalt;
@Override
public User queryByPhone(String phone) {
User user = null;
if(CommonUtil.checkPhone(phone)){
user = userMapper.selectByPhone(phone);
}
return user;
}
/*用户注册*/
@Transactional(rollbackFor = Exception.class) // 开启事务
@Override
public synchronized int userRegister(String phone, String password) { // synchronized:同步的方法,保证线程安全,该方法处理时,其他方法不能对其参数二次处理(phone和password)
int result = 0;//默认参数不正确
if( CommonUtil.checkPhone(phone)
&& (password != null && password.length()==32)){
//判断手机号在库中是否存在
User queryUser = userMapper.selectByPhone(phone);
if(queryUser == null){
//注册密码的md5二次加密。 给原始的密码加盐(salt)
String newPassword = DigestUtils.md5Hex( password + passwordSalt);
//注册u_user
User user = new User();
user.setPhone(phone);
user.setLoginPassword(newPassword);
user.setAddTime(new Date());
userMapper.insertReturnPrimaryKey(user);
//获取主键user.getId()
FinanceAccount account = new FinanceAccount();
account.setUid(user.getId());
account.setAvailableMoney(new BigDecimal("0"));
financeAccountMapper.insertSelective(account);
//成功result = 1
result = 1;
} else {
//手机号存在
result = 2;
}
}
return result;
}
/*登录*/
@Transactional(rollbackFor = Exception.class)
@Override
public User userLogin(String phone, String password) {
User user = null;
if( CommonUtil.checkPhone(phone) && (password != null && password.length() == 32)) {
String newPassword = DigestUtils.md5Hex( password + passwordSalt);
user = userMapper.selectLogin(phone,newPassword);
//更新最后登录时间
if( user != null){
user.setLastLoginTime(new Date());
userMapper.updateByPrimaryKeySelective(user);
}
}
return user;
}
/*更新实名认证信息*/
@Override
public boolean modifyRealname(String phone, String name, String idCard) {
int rows = 0;
if(!StringUtils.isAnyBlank(phone,name,idCard)){
rows = userMapper.updateRealname(phone,name,idCard);
}
return rows > 0 ;
}
/*获取用户和资金信息*/
@Override
public UserAccountInfo queryUserAllInfo(Integer uid) {
UserAccountInfo info = null;
if( uid != null && uid > 0 ) {
info = userMapper.selectUserAccountById(uid);
}
return info ;
}
/*查询用户*/
@Override
public User queryById(Integer uid) {
User user = null;
if( uid != null && uid > 0 ){
user = userMapper.selectByPrimaryKey(uid);
}
return user;
}
}
其中:
1、查询登录方法:(需要在dataservice模块mapper包下的UserMapper接口添加方法,并在resources/mappers/UserMapper.xml编写SQL语句):
/*登录*/
User selectLogin(@Param("phone") String phone, @Param("loginPassword") String newPassword);
这里使用newPassword,不使用loginPassword是为了避免一些数据库表中字段、关键字同名
<!--登录-->
<select id="selectLogin" resultMap="BaseResultMap">
select <include refid="Base_Column_List"></include>
from u_user
where phone = #{phone} and login_password = #{loginPassword}
</select>
在web模块的usercontroller类下添加:(userLogin结果集)
1、检查参数(电话是否标准,密码是否标准)
2、检查验证码是否正确(if(loginSmsService.checkSmsCode(phone,scode)))
3、访问data-service(User user = userService.userLogin(phone,pword);)
4、登录成功,生成token
package com.bjpowernode.front.controller;
import com.bjpowernode.api.model.User;
import com.bjpowernode.api.pojo.UserAccountInfo;
import com.bjpowernode.common.enums.RCode;
import com.bjpowernode.common.util.CommonUtil;
import com.bjpowernode.common.util.JwtUtil;
import com.bjpowernode.front.service.RealnameServiceImpl;
import com.bjpowernode.front.service.SmsService;
import com.bjpowernode.front.view.RespResult;
import com.bjpowernode.front.vo.RealnameVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.jute.compiler.generated.Rcc;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.management.relation.Relation;
import java.util.HashMap;
import java.util.Map;
@Api(tags = "用户功能")
@RestController
@RequestMapping("/v1/user")
public class UserController extends BaseController {
@Resource(name = "smsCodeRegisterImpl")
private SmsService smsService;
@Resource(name = "smsCodeLoginImpl")
private SmsService loginSmsService;
@Resource
private RealnameServiceImpl realnameService;
@Resource
private JwtUtil jwtUtil;
/**手机号注册用户*/
@ApiOperation(value = "手机号注册用户")
@PostMapping("/register")
public RespResult userRegister(@RequestParam String phone,
@RequestParam String pword,
@RequestParam String scode){
RespResult result = RespResult.fail();
//1.检查参数
if( CommonUtil.checkPhone(phone)){
if(pword !=null && pword.length() == 32 ){
//检查短信验证码
if( smsService.checkSmsCode(phone,scode)){
//可以注册
int registerResult = userService.userRegister(phone,pword);
if( registerResult == 1 ){
result = RespResult.ok();
} else if( registerResult == 2 ){
result.setRCode(RCode.PHONE_EXISTS);
} else {
result.setRCode(RCode.REQUEST_PARAM_ERR);
}
} else {
//短信验证码无效
result.setRCode(RCode.SMS_CODE_INVALID);
}
} else {
result.setRCode(RCode.REQUEST_PARAM_ERR);
}
} else {
//手机号格式不正确
result.setRCode(RCode.PHONE_FORMAT_ERR);
}
return result;
}
/** 手机号是否存在 */
@ApiOperation(value = "手机号是否注册过",notes = "在注册功能中,判断手机号是否可以注册")
@ApiImplicitParam(name = "phone",value = "手机号")
@GetMapping("/phone/exists")
public RespResult phoneExists(@RequestParam("phone") String phone){
RespResult result = new RespResult();
result.setRCode(RCode.PHONE_EXISTS);
//1.检查请求参数是否符合要求
if(CommonUtil.checkPhone(phone)){
//可以执行逻辑 ,查询数据库,调用数据服务
User user = userService.queryByPhone(phone);
if( user == null ){
//可以注册
result = RespResult.ok();
}
//把查询到的手机号放入redis。 然后检查手机号是否存在,可以查询redis
} else {
result.setRCode(RCode.PHONE_FORMAT_ERR);
}
return result;
}
/** 登录,获取token-jwt*/
@ApiOperation(value = "用户登录-获取访问token")
@PostMapping("/login")
public RespResult userLogin(@RequestParam String phone,
@RequestParam String pword,
@RequestParam String scode) throws Exception{
RespResult result = RespResult.fail();
if(CommonUtil.checkPhone(phone) && (pword != null && pword.length() == 32) ){
if(loginSmsService.checkSmsCode(phone,scode)){
//访问data-service
User user = userService.userLogin(phone,pword);
if( user != null){
//登录成功,生成token
Map<String, Object> data = new HashMap<>();
data.put("uid",user.getId());
String jwtToken = jwtUtil.createJwt(data,120); // 120分钟
result = RespResult.ok();
result.setAccessToken(jwtToken);
Map<String,Object> userInfo = new HashMap<>();
userInfo.put("uid",user.getId());
userInfo.put("phone",user.getPhone());
userInfo.put("name",user.getName());
result.setData(userInfo);
} else {
result.setRCode(RCode.PHONE_LOGIN_PASSWORD_INVALID);
}
} else {
result.setRCode(RCode.SMS_CODE_INVALID);
}
} else {
result.setRCode(RCode.REQUEST_PARAM_ERR);
}
return result;
}
/** 实名认证 vo: value object*/
@ApiOperation(value = "实名认证",notes = "提供手机号和姓名,身份证号。 认证姓名和身份证号是否一致")
@PostMapping("/realname")
public RespResult userRealname(@RequestBody RealnameVO realnameVO){
RespResult result = RespResult.fail();
result.setRCode(RCode.REQUEST_PARAM_ERR);
//1验证请求参数
if( CommonUtil.checkPhone(realnameVO.getPhone())){
if(StringUtils.isNotBlank(realnameVO.getName()) &&
StringUtils.isNotBlank(realnameVO.getIdCard())){
//判断用户已经做过
User user = userService.queryByPhone(realnameVO.getPhone());
if( user != null ){
if( StringUtils.isNotBlank(user.getName())){
result.setRCode(RCode.REALNAME_RETRY);
} else {
//有短信验证码,先不写
//调用第三方接口,判断认证结果
boolean realnameResult = realnameService.handleRealname(
realnameVO.getPhone(),realnameVO.getName(),
realnameVO.getIdCard());
if( realnameResult == true ){
result = RespResult.ok();
} else {
result.setRCode(RCode.REALNAME_FAIL);
}
}
}
}
}
return result;
}
/** 用户中心 */
@ApiOperation(value = "用户中心")
@GetMapping("/usercenter")
public RespResult userCenter(@RequestHeader(value = "uid",required = false) Integer uid){
RespResult result = RespResult.fail();
if( uid != null && uid > 0 ){
UserAccountInfo userAccountInfo = userService.queryUserAllInfo(uid);
if( userAccountInfo != null ){
result = RespResult.ok();
Map<String,Object> data = new HashMap<>();
data.put("name",userAccountInfo.getName());
data.put("phone",userAccountInfo.getPhone());
data.put("headerUrl",userAccountInfo.getHeaderImage());
data.put("money",userAccountInfo.getAvailableMoney());
if( userAccountInfo.getLastLoginTime() != null){
data.put("loginTime", DateFormatUtils.format(
userAccountInfo.getLastLoginTime(),"yyyy-MM-dd HH:mm:ss"));
} else {
data.put("loginTime","-");
}
result.setData(data);
}
}
return result;
}
}
其中:
1、在common模块util包下,编写一个工具类:(JwtUtil)
package com.bjpowernode.common.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.apache.commons.lang3.time.DateUtils;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
public class JwtUtil {
private String selfKey;
public JwtUtil(String selfKey) {
this.selfKey = selfKey;
}
//创建jwt
public String createJwt(Map<String,Object> data, Integer minute) throws Exception{
Date curDate = new Date();
SecretKey secretKey = Keys.hmacShaKeyFor(selfKey.getBytes(StandardCharsets.UTF_8));
String jwt = Jwts.builder().signWith(secretKey, SignatureAlgorithm.HS256)
.setExpiration(DateUtils.addMinutes(curDate,minute))
.setIssuedAt(curDate)
.setId(UUID.randomUUID().toString().replaceAll("-","").toUpperCase())
.addClaims(data)
.compact();
return jwt;
}
//读取jwt
public Claims readJwt(String jwt) throws Exception{
SecretKey secretKey = Keys.hmacShaKeyFor(selfKey.getBytes(StandardCharsets.UTF_8));
Claims body = Jwts.parserBuilder().setSigningKey(secretKey)
.build().parseClaimsJws(jwt).getBody();
return body;
}
}
2、在web模块下resources/application.yml配置jwt信息:
jwt:
secret: 342903934cb944808920b642616b3e76
3、在web模块的启动类创建JwtUtil:
package com.bjpowernode.front;
import com.bjpowernode.common.util.JwtUtil;
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
//启动swagger 和 ui
@EnableSwaggerBootstrapUI
@EnableSwagger2
//启动dubbo服务
@EnableDubbo
@SpringBootApplication
public class MicrWebApplication {
@Value("${jwt.secret}")
private String secertKey;
//创建JwtUtil
@Bean
public JwtUtil jwtUtil(){
JwtUtil jwtUtil = new JwtUtil(secertKey);
return jwtUtil;
}
public static void main(String[] args) {
SpringApplication.run(MicrWebApplication.class, args);
}
}