feat: 登录;获取用户信息

This commit is contained in:
Bunny 2024-12-04 20:04:12 +08:00
parent 4ec11f0f69
commit 7bd921a746
21 changed files with 335 additions and 68 deletions

View File

@ -5,18 +5,17 @@ package com.atguigu.daijia.common.util;
*/
public class AuthContextHolder {
private static ThreadLocal<Long> userId = new ThreadLocal<Long>();
public static void setUserId(Long _userId) {
userId.set(_userId);
}
private static final ThreadLocal<Long> userId = new ThreadLocal<>();
public static Long getUserId() {
return userId.get();
}
public static void setUserId(Long _userId) {
userId.set(_userId);
}
public static void removeUserId() {
userId.remove();
}
}

View File

@ -82,9 +82,8 @@ public class RedisConfig {
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}

View File

@ -33,7 +33,7 @@ public class WebSecurityConfig {
private CustomMd5PasswordEncoder customMd5PasswordEncoder;
@Autowired
private RedisTemplate redisTemplate;
private RedisTemplate<Object,Object> redisTemplate;
@Autowired
private SysLoginLogFeignClient sysLoginLogFeignClient;
@ -88,5 +88,4 @@ public class WebSecurityConfig {
return http.build();
}
}

View File

@ -31,13 +31,12 @@ import java.util.stream.Collectors;
*/
public class TokenAuthenticationFilter extends OncePerRequestFilter {
private RedisTemplate redisTemplate;
private final RedisTemplate<Object,Object> redisTemplate;
private String ADMIN_LOGIN_KEY_PREFIX = "admin:login:";
private AntPathMatcher antPathMatcher = new AntPathMatcher();
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
public TokenAuthenticationFilter(RedisTemplate redisTemplate) {
public TokenAuthenticationFilter(RedisTemplate<Object,Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@ -70,12 +69,13 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
String token = request.getHeader("token");
logger.info("token:"+token);
if (StringUtils.hasText(token)) {
SysUser sysUser = (SysUser)redisTemplate.opsForValue().get(ADMIN_LOGIN_KEY_PREFIX+token);
String ADMIN_LOGIN_KEY_PREFIX = "admin:login:";
SysUser sysUser = (SysUser)redisTemplate.opsForValue().get(ADMIN_LOGIN_KEY_PREFIX +token);
logger.info("sysUser:"+JSON.toJSONString(sysUser));
if (null != sysUser) {
AuthContextHolder.setUserId(sysUser.getId());
if (null != sysUser.getUserPermsList() && sysUser.getUserPermsList().size() > 0) {
if (null != sysUser.getUserPermsList() && !sysUser.getUserPermsList().isEmpty()) {
List<SimpleGrantedAuthority> authorities = sysUser.getUserPermsList().stream().filter(code -> StringUtils.hasText(code.trim())).map(code -> new SimpleGrantedAuthority(code.trim())).collect(Collectors.toList());
return new UsernamePasswordAuthenticationToken(sysUser.getUsername(), null, authorities);
} else {

View File

@ -27,7 +27,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
throw new UsernameNotFoundException("用户名不存在!");
}
if(!"admin".equals(sysUser.getUsername()) && sysUser.getStatus().intValue() == 0) {
if(!"admin".equals(sysUser.getUsername()) && sysUser.getStatus() == 0) {
throw new RuntimeException("账号已停用");
}
List<String> userPermsList = securityLoginFeignClient.findUserPermsList(sysUser.getId()).getData();

View File

@ -5,10 +5,8 @@ import lombok.Data;
@Data
public class UpdateWxPhoneForm {
@Schema(description = "客户Id")
private Long customerId;
private String code;
}

View File

@ -9,9 +9,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableDiscoveryClient
@EnableFeignClients
public class ServerGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ServerGatewayApplication.class, args);
}
}

View File

@ -18,7 +18,6 @@ import reactor.core.publisher.Mono;
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange);

View File

@ -1,9 +1,26 @@
package com.atguigu.daijia.customer.client;
import com.atguigu.daijia.common.result.Result;
import com.atguigu.daijia.model.form.customer.UpdateWxPhoneForm;
import com.atguigu.daijia.model.vo.customer.CustomerLoginVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(value = "service-customer")
public interface CustomerInfoFeignClient {
// 登录客户端接口
@GetMapping("/customer/info/login/{code}")
Result<Long> login(@PathVariable String code);
// 获取乘客用户信息
@GetMapping("/customer/info/getCustomerLoginInfo/{customerId}")
Result<CustomerLoginVo> getCustomerLoginInfo(@PathVariable("customerId") Long customerId);
// 更新客户微信手机号码
@PostMapping("/customer/info/updateWxPhoneNumber")
Result<Boolean> updateWxPhoneNumber(@RequestBody UpdateWxPhoneForm updateWxPhoneForm);
}

View File

@ -1,8 +0,0 @@
spring.application.name=service-coupon
spring.profiles.active=dev
spring.main.allow-bean-definition-overriding=true
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.prefix=${spring.application.name}
spring.cloud.nacos.config.file-extension=yaml
spring.cloud.nacos.config.shared-configs[0].data-id=common-account.yaml

View File

@ -18,6 +18,10 @@
</properties>
<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -9,7 +9,6 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceCustomerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceCustomerApplication.class, args);
}

View File

@ -2,28 +2,38 @@ package com.atguigu.daijia.customer.controller;
import com.atguigu.daijia.common.result.Result;
import com.atguigu.daijia.customer.service.CustomerInfoService;
import com.atguigu.daijia.model.entity.customer.CustomerInfo;
import com.atguigu.daijia.model.form.customer.UpdateWxPhoneForm;
import com.atguigu.daijia.model.vo.customer.CustomerLoginVo;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@RequestMapping("/customer/info")
@SuppressWarnings({"unchecked", "rawtypes"})
public class CustomerInfoController {
@Autowired
private CustomerInfoService customerInfoService;
@Autowired
private CustomerInfoService customerInfoService;
@Operation(summary = "获取客户基本信息")
@GetMapping("/getCustomerInfo/{customerId}")
public Result<CustomerInfo> getCustomerInfo(@PathVariable Long customerId) {
return Result.ok(customerInfoService.getById(customerId));
}
@Operation(summary = "获取客户登录信息")
@GetMapping("/getCustomerLoginInfo/{customerId}")
public Result<CustomerLoginVo> getCustomerLoginInfo(@PathVariable Long customerId) {
CustomerLoginVo customerLoginVo = customerInfoService.getCustomerInfo(customerId);
return Result.ok(customerLoginVo);
}
@Operation(summary = "小程序授权登录")
@GetMapping("/login/{code}")
public Result<Long> login(@PathVariable String code) {
return Result.ok(customerInfoService.login(code));
}
@Operation(summary = "更新客户微信手机号码")
@PostMapping("/updateWxPhoneNumber")
public Result<Boolean> updateWxPhoneNumber(@RequestBody UpdateWxPhoneForm updateWxPhoneForm) {
return Result.ok(customerInfoService.updateWxPhoneNumber(updateWxPhoneForm));
}
}

View File

@ -1,8 +1,29 @@
package com.atguigu.daijia.customer.service;
import com.atguigu.daijia.model.entity.customer.CustomerInfo;
import com.atguigu.daijia.model.form.customer.UpdateWxPhoneForm;
import com.atguigu.daijia.model.vo.customer.CustomerLoginVo;
import com.baomidou.mybatisplus.extension.service.IService;
public interface CustomerInfoService extends IService<CustomerInfo> {
/**
* 微信小程序登录接口
* @param code 登录码
* @return 登录内容
*/
Long login(String code);
/**
* 获取客户登录信息
* @param customerId 乘客端id
* @return 客户相关信息
*/
CustomerLoginVo getCustomerInfo(Long customerId);
/**
* 更新客户微信手机号码
* @param updateWxPhoneForm 更新用户手机号表单
* @return 是否更新成功
*/
Boolean updateWxPhoneNumber(UpdateWxPhoneForm updateWxPhoneForm);
}

View File

@ -1,16 +1,125 @@
package com.atguigu.daijia.customer.service.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.atguigu.daijia.common.execption.GuiguException;
import com.atguigu.daijia.common.result.ResultCodeEnum;
import com.atguigu.daijia.customer.mapper.CustomerInfoMapper;
import com.atguigu.daijia.customer.mapper.CustomerLoginLogMapper;
import com.atguigu.daijia.customer.service.CustomerInfoService;
import com.atguigu.daijia.model.entity.customer.CustomerInfo;
import com.atguigu.daijia.model.entity.customer.CustomerLoginLog;
import com.atguigu.daijia.model.form.customer.UpdateWxPhoneForm;
import com.atguigu.daijia.model.vo.customer.CustomerLoginVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, CustomerInfo> implements CustomerInfoService {
@Autowired
private WxMaService wxMaService;
@Autowired
private CustomerInfoMapper customerInfoMapper;
@Autowired
private CustomerLoginLogMapper customerLoginLogMapper;
/**
* 微信小程序登录接口
*
* @param code 登录码
* @return 登录内容
*/
@Override
public Long login(String code) {
// 1 获取code值使用微信工具包对象获取微信唯一标识openid
String openid;
try {
WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
openid = sessionInfo.getOpenid();
} catch (WxErrorException e) {
throw new RuntimeException(e);
}
// 2 根据openid查询数据库表判断是否第一次登录
// 如果openid不存在返回null如果存在返回一条记录
LambdaQueryWrapper<CustomerInfo> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(CustomerInfo::getWxOpenId, openid);
CustomerInfo customerInfo = customerInfoMapper.selectOne(wrapper);
// 3 如果第一次登录添加信息到用户表
if (customerInfo == null) {
customerInfo = new CustomerInfo();
customerInfo.setNickname(String.valueOf(System.currentTimeMillis()));
customerInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
customerInfo.setWxOpenId(openid);
customerInfoMapper.insert(customerInfo);
}
// 4 记录登录日志信息
CustomerLoginLog customerLoginLog = new CustomerLoginLog();
customerLoginLog.setCustomerId(customerInfo.getId());
customerLoginLog.setMsg("小程序登录");
customerLoginLogMapper.insert(customerLoginLog);
// 5 返回用户id
return customerInfo.getId();
}
/**
* 获取客户登录信息
*
* @param customerId 乘客端id
* @return 客户相关信息
*/
@Override
public CustomerLoginVo getCustomerInfo(Long customerId) {
// 1 根据用户id查询用户信息
CustomerInfo customerInfo = customerInfoMapper.selectById(customerId);
// 2 封装到CustomerLoginVo
CustomerLoginVo customerLoginVo = new CustomerLoginVo();
BeanUtils.copyProperties(customerInfo, customerLoginVo);
String phone = customerInfo.getPhone();
customerLoginVo.setIsBindPhone(StringUtils.hasText(phone));
// 3 CustomerLoginVo返回
return customerLoginVo;
}
/**
* 更新客户微信手机号码
*
* @param updateWxPhoneForm 更新用户手机号表单
* @return 是否更新成功
*/
@Override
public Boolean updateWxPhoneNumber(UpdateWxPhoneForm updateWxPhoneForm) {
// 1 根据code值获取微信绑定手机号码
try {
WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(updateWxPhoneForm.getCode());
String phoneNumber = phoneNoInfo.getPhoneNumber();
// 更新用户信息
Long customerId = updateWxPhoneForm.getCustomerId();
CustomerInfo customerInfo = customerInfoMapper.selectById(customerId);
customerInfo.setPhone(phoneNumber);
customerInfoMapper.updateById(customerInfo);
return true;
} catch (WxErrorException e) {
throw new GuiguException(ResultCodeEnum.DATA_ERROR);
}
}
}

View File

@ -1,8 +0,0 @@
spring.application.name=service-customer
spring.profiles.active=dev
spring.main.allow-bean-definition-overriding=true
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.prefix=${spring.application.name}
spring.cloud.nacos.config.file-extension=yaml
spring.cloud.nacos.config.shared-configs[0].data-id=common-account.yaml

View File

@ -10,10 +10,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableDiscoveryClient
@EnableFeignClients
public class WebCustomerApplication {
public static void main(String[] args) {
SpringApplication.run(WebCustomerApplication.class, args);
}
}

View File

@ -1,18 +1,49 @@
package com.atguigu.daijia.customer.controller;
import com.atguigu.daijia.common.login.GuiguLogin;
import com.atguigu.daijia.common.result.Result;
import com.atguigu.daijia.common.util.AuthContextHolder;
import com.atguigu.daijia.customer.service.CustomerService;
import com.atguigu.daijia.model.form.customer.UpdateWxPhoneForm;
import com.atguigu.daijia.model.vo.customer.CustomerLoginVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@Slf4j
@Tag(name = "客户API接口管理")
@RestController
@RequestMapping("/customer")
@SuppressWarnings({"unchecked", "rawtypes"})
public class CustomerController {
@Autowired
private CustomerService customerInfoService;
@Operation(summary = "获取客户登录信息")
@GuiguLogin
@GetMapping("/getCustomerLoginInfo")
public Result<CustomerLoginVo> getCustomerLoginInfo() {
// 调用service
CustomerLoginVo customerLoginVo = customerInfoService.getCustomerInfo();
return Result.ok(customerLoginVo);
}
@Operation(summary = "小程序授权登录")
@GetMapping("/login/{code}")
public Result<String> wxLogin(@PathVariable String code) {
String login = customerInfoService.login(code);
return Result.ok(login);
}
@Operation(summary = "更新用户微信手机号")
@GuiguLogin
@PostMapping("/updateWxPhone")
public Result<Boolean> updateWxPhone(@RequestBody UpdateWxPhoneForm updateWxPhoneForm) {
updateWxPhoneForm.setCustomerId(AuthContextHolder.getUserId());
Boolean updateWxPhoneNumber = customerInfoService.updateWxPhoneNumber(updateWxPhoneForm);
return Result.ok(updateWxPhoneNumber);
}
}

View File

@ -1,6 +1,28 @@
package com.atguigu.daijia.customer.service;
import com.atguigu.daijia.model.form.customer.UpdateWxPhoneForm;
import com.atguigu.daijia.model.vo.customer.CustomerLoginVo;
public interface CustomerService {
/**
* 微信小程序登录接口
* @param code 登录码
* @return 登录内容
*/
String login(String code);
/**
* 获取客户登录信息
*
* @return 客户相关信息
*/
CustomerLoginVo getCustomerInfo();
/**
* 更新客户微信手机号码
*
* @param updateWxPhoneForm 更新用户手机号表单
* @return 是否更新成功
*/
Boolean updateWxPhoneNumber(UpdateWxPhoneForm updateWxPhoneForm);
}

View File

@ -1,16 +1,105 @@
package com.atguigu.daijia.customer.service.impl;
import com.atguigu.daijia.common.constant.RedisConstant;
import com.atguigu.daijia.common.execption.GuiguException;
import com.atguigu.daijia.common.result.Result;
import com.atguigu.daijia.common.result.ResultCodeEnum;
import com.atguigu.daijia.common.util.AuthContextHolder;
import com.atguigu.daijia.customer.client.CustomerInfoFeignClient;
import com.atguigu.daijia.customer.service.CustomerService;
import com.atguigu.daijia.model.form.customer.UpdateWxPhoneForm;
import com.atguigu.daijia.model.vo.customer.CustomerLoginVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerInfoFeignClient client;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private CustomerInfoFeignClient customerInfoFeignClient;
/**
* 微信小程序登录接口
*
* @param code 登录码
* @return 登录内容
*/
@Override
public String login(String code) {
// 1 拿着code进行远程调用返回用户id
Result<Long> loginResult = client.login(code);
// 2 判断如果返回失败了返回错误提示
Integer codeResult = loginResult.getCode();
if (codeResult != 200) {
throw new GuiguException(ResultCodeEnum.DATA_ERROR);
}
// 3 获取远程调用返回用户id
Long customerId = loginResult.getData();
// 4 判断返回用户id是否为空如果为空返回错误提示
if (customerId == null) {
throw new GuiguException(ResultCodeEnum.DATA_ERROR);
}
// 5 生成token字符串
String token = UUID.randomUUID().toString().replaceAll("-", "");
// 6 把用户id放到Redis设置过期时间
redisTemplate.opsForValue().set(RedisConstant.USER_LOGIN_KEY_PREFIX + token,
customerId.toString(),
RedisConstant.USER_LOGIN_KEY_TIMEOUT,
TimeUnit.SECONDS);
// 7 返回token
return token;
}
/**
* 获取客户登录信息
*
* @return 客户相关信息
*/
@Override
public CustomerLoginVo getCustomerInfo() {
// 1 从ThreadLocal获取用户id
Long customerId = AuthContextHolder.getUserId();
// 根据用户id进行远程调用 得到用户信息
Result<CustomerLoginVo> customerLoginVoResult = customerInfoFeignClient.getCustomerLoginInfo(customerId);
Integer code = customerLoginVoResult.getCode();
if (code != 200) throw new GuiguException(ResultCodeEnum.DATA_ERROR);
CustomerLoginVo customerLoginVo = customerLoginVoResult.getData();
if (customerLoginVo == null) throw new GuiguException(ResultCodeEnum.DATA_ERROR);
// 5 返回用户信息
return customerLoginVo;
}
/**
* 更新客户微信手机号码
*
* @param updateWxPhoneForm 更新用户手机号表单
* @return 是否更新成功
*/
@Override
public Boolean updateWxPhoneNumber(UpdateWxPhoneForm updateWxPhoneForm) {
Result<Boolean> booleanResult = customerInfoFeignClient.updateWxPhoneNumber(updateWxPhoneForm);
System.out.println(booleanResult.getData());
return true;
}
}

View File

@ -1,8 +0,0 @@
spring.application.name=web-customer
spring.profiles.active=dev
spring.main.allow-bean-definition-overriding=true
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.prefix=${spring.application.name}
spring.cloud.nacos.config.file-extension=yaml
spring.cloud.nacos.config.shared-configs[0].data-id=common-account.yaml