开发在线法律咨询平台的设计与实现Day2
今日完成
登录接口
UserController.java
/**
* 用户登录接口
* @param userAccount 用户账号
* @param userPassword 用户密码
* @return 返回脱敏后的用户数据
*/
@PostMapping("/login")
public BaseResponse<String> userLogin(String userAccount,String userPassword ){
if(StringUtils.isAnyBlank(userAccount,userPassword)){
throw new BusinessException(ErrorCode.NULL_ERROR);
}
String token = userService.userLogin(userAccount, userPassword);
return ResultUtils.success(token);
};
UserServiceImpl.java
//登录业务层
@Override
public String userLogin(String userAccount, String userPassword) {
//验证是否非空,不为空执行下一步
if (StringUtils.isAnyBlank(userAccount,userPassword)){
throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号密码为空");
//账号不能小于4位
}
if (userAccount.length()<4){
throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号不能小于4位");
}
//密码不能小于8位
if (userPassword.length()<8 ){
throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不能小于8位");
}
//账户不包含特殊字符
String regEx="[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*() ——+|{}【】‘;:”“’。,、?]";
Matcher matcher = Pattern.compile(regEx).matcher(userAccount);
if (matcher.find()){
throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号包含特殊字符");
}
//加密
String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
//查询用户是否存在
QueryWrapper<User> qw = new QueryWrapper<>();
qw.eq("userAccount",userAccount);
qw.eq("userPassword",encryptPassword);
User user = userMapper.selectOne(qw);
//用户不存在
if(user ==null){
log.info(" user login failed, userAccount cannot match userPassword");
throw new BusinessException(ErrorCode.FAIL_SEARCH,"账号或密码错误");
}
Map<String, Object> claims = new HashMap();
claims.put("id",user.getId());
claims.put("username",user.getUsername());
String token = JwtUtil.genToken(claims);
getSafetyUser(user);//脱敏
return token;
}
//用户脱敏
@Override
public User getSafetyUser(User originUser){
if(originUser == null){
throw new BusinessException(ErrorCode.PARAMS_ERROR,"脱敏失败");
}
User safetyUser = new User();
safetyUser.setId(originUser.getId());
safetyUser.setUsername(originUser.getUsername());
safetyUser.setUserAccount(originUser.getUserAccount());
safetyUser.setAvatarUrl(originUser.getAvatarUrl());
safetyUser.setUserRole(originUser.getUserRole());
safetyUser.setGender(originUser.getGender());
safetyUser.setPhone(originUser.getPhone());
safetyUser.setEmail(originUser.getEmail());
safetyUser.setUserStatus(originUser.getUserStatus());
safetyUser.setCreateTime(originUser.getCreateTime());
return safetyUser;
}
整合jwt
导入依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
jwt工具类
JwtUtil.java
public class JwtUtil {
//接受业务数据,生成token并返回
public static String genToken(Map<String, Object> claims){
return JWT.create()
.withClaim("claims",claims)
.withExpiresAt(new Date(System.currentTimeMillis() + 1000*60*60*24))
.sign(Algorithm.HMAC256(UserContant.SALT));
}
//接受token,验证token是否有效
public static Map<String,Object> parseToken(String token){
return JWT.require(Algorithm.HMAC256(UserContant.SALT))
.build()
.verify(token)
.getClaim("claims")
.asMap();
}
}
拦截器
LoginInterceptor.java
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
try{
// 解析token
Map<String,Object> claims = JwtUtil.parseToken(token);
ThreadLoaclUtil.set(claims);
return true;
}catch (Exception e){
response.setStatus(401);
return false;
}
}
// 请求处理完毕移THREAD_LOCAL中除线程变量
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
ThreadLoaclUtil.remove();
}
}
配置拦截器
WebConfig.java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//登录接口和注册接口不需要拦截
registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","user/register");
}
}
开发中遇到的问题
一、无法获取对象
问题描述: 程序可以从数据库中拿到数据,却无法存在对象中。
解决过程: 配置map-underscore-to-camel-case: true
具体实现:
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true #下划线命名法自动映射为驼峰命名法的功能。解决了数据库中表字段名与实体类属性名不一致的问题。
二、获取用户信息过于繁琐
问题描述: 每次请求访问时,要想拿到token中存取的数据,都要在每个方法中以参数的形式获取请求头中的Authorization,在解析token,太过繁琐。
解决过程: 由于在请求拦截时每次都会获取一次Authorization并解析token,我们只需要引入ThreadLocal来提供线程局部变量,在请求拦截时把解析后的token存储在ThreadLocal线程中,然后在每个请求方法下使用ThreadLocal.get()方法就可以拿到。
具体实现:
封装一个工具类
public class ThreadLoaclUtil {
private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();
// 获取线程变量
public static <T> T get() {
return (T)THREAD_LOCAL.get();
}
// 设置线程变量
public static void set(Object value) {
THREAD_LOCAL.set(value);
}
// 移除线程变量
public static void remove() {
THREAD_LOCAL.remove();
}
}
请求拦截前
ThreadLoaclUtil.set(claims);
一次响应结束后
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
ThreadLoaclUtil.remove();
}
需要token解析参数时
Map<String,Object> map = ThreadLoaclUtil.get();
小组会议(设计系统)
在线法律咨询平台的设计与实现
设计
-
√ 用户注册与登录:用户可以注册个人账号,并通过登录方式访问平台。
-
√提问咨询:用户可以提出法律问题,并描述详细情况,以便律师准确理解问题。
-
√律师匹配:系统可以根据用户的问题需求,自动匹配或推荐合适的专业律师进行解答。
-
√在线交流:用户和律师之间可以通过文字、语音或视频等方式进行实时在线交流,解答疑问。
-
√文件上传:用户可以上传相关法律文件或证据,以便律师更好地了解问题情况并提供解决方案。
-
√支付结算:平台支持用户支付法律咨询费用的功能,平台进行结算并支付给律师。
- √线上咨询记录:系统将记录用户与律师之间的交流内容和咨询记录,方便双方查阅。
-
用户评价与反馈:用户可以对咨询服务的质量和效果进行评价,并留下反馈意见。
-
法律知识库:平台可能提供法律知识库,包括法律条文、案例分析等内容,方便用户查询。
-
用户管理:系统可以管理用户信息、订单记录,保护用户隐私和数据安全。
登录——>描述问题——>系统列出匹配律师——>支付页面——>在线交流