登陆代码优化,面向方法编程,优化ing

lzm
廖忠美 2024-06-24 15:38:13 +08:00
parent 0238e2960d
commit 407642d8b5
18 changed files with 276 additions and 91 deletions

File diff suppressed because one or more lines are too long

View File

@ -20,4 +20,7 @@ public class UserAccount {
@ApiModelProperty("密码/")
private String password;
// @ApiModelProperty("uuid")
// private String UUID;
}

View File

@ -5,4 +5,7 @@ public class PermissionConstants {
public static final String CODE_LIST = "codeList";
public static final String ROLE = "role";
public static final String PERMISSION_CODE = "permission_code";
public static final String USER_CACHE_KEY = "user:username:";
public static final String USER_KEY = "user:key:";
public static final String USER_NAME = "username";
}

View File

@ -3,7 +3,9 @@ package com.auth.server;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@SpringBootApplication
@MapperScan("com.auth.server.mapper")
@ -15,4 +17,9 @@ public class EtlAuthServerApplication {
SpringApplication.run(EtlAuthServerApplication.class, args);
}
@Bean
public BCryptPasswordEncoder encryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}

View File

@ -0,0 +1,18 @@
//package com.auth.server.config;
//import com.auth.server.interceptor.UserInterceptor;
//import com.auth.server.mapper.UserMangeMapper;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//@Configuration
//public class MvcConfig implements WebMvcConfigurer {
// @Autowired
// private UserMangeMapper userMangeMapper;
// @Override
// public void addInterceptors(InterceptorRegistry registry) {
// //添加拦截器,排除/路径和 /login路径
// registry.addInterceptor(new UserInterceptor(userMangeMapper))
// .excludePathPatterns("/","/user/login");
// }
//}

View File

@ -1,13 +1,17 @@
package com.auth.server.controller;
import com.alibaba.fastjson2.JSON;
import com.alibaba.nacos.api.model.v2.Result;
import com.auth.common.entity.UserAccount;
import com.auth.common.enums.PermissionConstants;
import com.auth.server.service.UserManageService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.etl.common.enums.ResponseCodeEnum;
import com.etl.common.result.CommonResult;
import com.etl.jwt.util.JwtTokenUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
@ -16,10 +20,14 @@ import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* controller
@ -33,49 +41,105 @@ public class LoginControler {
private UserManageService userManageService;
@Resource
private JwtTokenUtil jwtTokenUtil;
//用户登录(使用用户名)
@PostMapping("/login")
public Result<Object> UserLogin(@RequestBody UserAccount user)
{
String username=user.getUsername();
String password=user.getPassword();
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* (使)
* @param user
* @return
*/
@ApiOperation(value = "用户登录")
@ApiOperationSupport(author = "liz")
@RequestMapping(value = "/login",method = RequestMethod.POST)
public Result<Object> userLogin(@RequestBody UserAccount user) {
// 获取用户名
String username = user.getUsername();
// 获取密码
String password = user.getPassword();
// 参数校验
Result result = checkUser(username, password);
if (result != null) {
return result;
}
// 创建SimpleAccountRealm并添加账户信息
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
// 确保这里添加的用户名和密码与用户提供的匹配
simpleAccountRealm.addAccount(username, password, user.getRoles());
// 配置SecurityManager并设置Realm
DefaultSecurityManager securityManager = new DefaultSecurityManager(simpleAccountRealm);
// 设置SecurityManager
SecurityUtils.setSecurityManager(securityManager);
//shiro验证
Subject subject= SecurityUtils.getSubject();
log.info("!11"+subject);
Subject subject = SecurityUtils.getSubject();
//根据用户名密码生成一个令牌
AuthenticationToken token=new UsernamePasswordToken(username,password);
AuthenticationToken token = new UsernamePasswordToken(username, password);
try {
//执行登录操作
// TODO 使用异步处理登录操作。在执行登录操作时,可以使用异步处理方式,避免阻塞主线程,提高系统性能。
subject.login(token);
//将用户信息存入redis
saveUserInfoToRedis(username, user);
} catch (UnknownAccountException e) {
log.info("登录用户不存在:{}",e);
return new Result<>(416,"用户不存在",username);
log.info("登录用户不存在:{}", e);
return new Result<>(416, "用户不存在", username);
} catch (IncorrectCredentialsException e) {
log.info("登录密码错误");
return new Result<>(412,"密码错误,请重新登录",password);
}catch (AuthenticationException e) {
return new Result<>(412, "密码错误,请重新登录", password);
} catch (AuthenticationException e) {
log.warn("用户登录异常:" + e.getMessage());
return new Result<>(416,"账户异常",username);
return new Result<>(416, "账户异常", username);
}
//获取登录用户信息
UserAccount account = userManageService.getOne(new QueryWrapper<UserAccount>().eq("username",username));
// 通过 jwtTokenUtil 生成 JWT 令牌和刷新令牌
Map<String, Object> tokenMap = jwtTokenUtil
.generateTokenAndRefreshToken(String.valueOf(account.getId()), username);
// 用户角色映射表中中查询用户角色
userManageService.getOne(new QueryWrapper<UserAccount>().eq("username",username)).getRoles();
return Result.success(tokenMap);
UserAccount account = userManageService.getOne(new QueryWrapper<UserAccount>().eq(PermissionConstants.USER_NAME, username));
// TODO 使用Redis等缓存技术将用户信息存储在内存中当需要查询用户信息时先从缓存中获取如果缓存中没有再查询数据库并将结果存入缓存
saveAllUserInfoToRedis(account);
// TODO 收集链接
// TODO 对密码进行加密存储。将用户密码进行加密存储,可以避免明文密码泄露的风险,同时可以提高系统安全性
// TODO 使用随机盐值:在每次加密时生成一个随机的盐值,并将其与密码一起进行加密。这样即使两个用户使用相同的密码,他们的加密结果也会不同,从而增加了破解的难度。
// TODO 定期更新密码:要求用户定期更改密码,并强制要求新密码必须包含大写字母、小写字母、数字和特殊字符等元素,以提高密码复杂度。
// TODO 限制登录尝试次数:限制用户在一定时间内只能尝试登录有限的次数,如果超过限制则锁定账户或延迟解锁时间,以防止暴力破解攻击
// 密码加密 数据库密码跟输入密码做比对
boolean matches = bCryptPasswordEncoder.matches(password, account.getPassword());
if (matches){
// 通过 jwtTokenUtil 生成 JWT 令牌和刷新令牌
Map<String, Object> tokenMap = jwtTokenUtil
.generateTokenAndRefreshToken(String.valueOf(account.getId()), username);
// 用户角色映射表中中查询用户角色
userManageService.getOne(new QueryWrapper<UserAccount>().eq(PermissionConstants.USER_NAME, username)).getRoles();
return Result.success(tokenMap);
}else{
throw new AuthenticationException("密码错误");
}
}
private void saveAllUserInfoToRedis(UserAccount account) {
stringRedisTemplate.opsForValue().set(PermissionConstants.USER_KEY+account.getId(),
JSON.toJSONString(account),24,TimeUnit.HOURS);
}
private void saveUserInfoToRedis(String username, UserAccount user) {
stringRedisTemplate.opsForValue().set(PermissionConstants.USER_CACHE_KEY + username,
JSON.toJSONString(user), 30 * 60, TimeUnit.MINUTES);
}
private Result checkUser(String username, String password) {
// 检查用户名和密码的合法性
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
return new Result<>(400, "用户名或密码不能为空");
}
if (username.length() < 3 || username.length() > 20) {
return new Result<>(400, "用户名长度必须在6-20个字符之间");
}
if (password.length() < 3 || password.length() > 20) {
return new Result<>(400, "密码长度必须在6-20个字符之间");
}
return null;
}
/**
@ -88,14 +152,17 @@ public class LoginControler {
* JWT access_token access_token使
* JWT 使 JWT access_token access_token
* 使refresh tokentoken
*
* <p>
* refresh_token access_token access_token refresh_token
* redis
*
* @param token
* @return
*/
@GetMapping("/token/refresh")
public CommonResult<Object> refreshToken(@RequestHeader(value = "${auth.jwt.header}") String token){
@RequestMapping(value = "/token/refresh",method = RequestMethod.GET)
@ApiOperation(value = "刷新令牌")
@ApiOperationSupport(author = "liz")
public CommonResult<Object> refreshToken(@RequestHeader(value = "${auth.jwt.header}") String token) {
token = com.auth.server.util.SecurityUtils.replaceTokenPrefix(token);
if (StringUtils.isEmpty(token)) {
@ -105,7 +172,7 @@ public class LoginControler {
// 对Token解签名并验证Token是否过期
boolean isJwtNotValid = jwtTokenUtil.isTokenExpired(token);
if(isJwtNotValid){
if (isJwtNotValid) {
return new CommonResult<>(ResponseCodeEnum.TOKEN_INVALID.getCode(),
ResponseCodeEnum.TOKEN_INVALID.getMessage());
}
@ -122,7 +189,7 @@ public class LoginControler {
// 如果用的不是 redis 中的 refreshToken 进行刷新令牌,则不能刷新。
// 如果使用 redis 中已过期的 refreshToken 也不能刷新令牌。
boolean isRefreshTokenNotExisted = jwtTokenUtil.isRefreshTokenNotExistCache(token);
if(isRefreshTokenNotExisted){
if (isRefreshTokenNotExisted) {
return new CommonResult<>(ResponseCodeEnum.REFRESH_TOKEN_INVALID.getCode(),
ResponseCodeEnum.REFRESH_TOKEN_INVALID.getMessage());
}
@ -130,6 +197,7 @@ public class LoginControler {
//String us = jwtTokenUtil.getUserIdFromToken(token);
Map<String, Object> tokenMap = jwtTokenUtil.refreshTokenAndGenerateToken(userId, username);
return new CommonResult<>(200, ResponseCodeEnum.SUCCESS.getMessage(),tokenMap);
return new CommonResult<>(200, ResponseCodeEnum.SUCCESS.getMessage(), tokenMap);
}
}

View File

@ -18,7 +18,7 @@ import java.util.List;
import java.util.Map;
/**
* controller
* controller
*/
@RestController
@Api(tags ="权限-API")

View File

@ -7,4 +7,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
public interface UserManageService extends IService<UserAccount> {
}

View File

@ -1,6 +1,7 @@
package com.auth.server.service.impl;
import com.auth.common.entity.RolesPermission;
import com.auth.common.enums.PermissionConstants;
import com.auth.server.mapper.PermissionMapper;
import com.auth.server.service.PermissionService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -18,29 +19,43 @@ import java.util.List;
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, RolesPermission> implements PermissionService {
@Autowired
private PermissionMapper permissionMapper;
@Override
public boolean permissionAdd(String roles, List<String> codeList) {
RolesPermission rolesPermission = new RolesPermission();
rolesPermission.setRole(roles);
int result = 0;
RolesPermission role = permissionMapper.selectOne(new QueryWrapper<RolesPermission>().eq("role",roles));
RolesPermission role = getRoleByName(roles);
if(role!=null){
//去掉头尾括号,并转为列表
List<String> list = new java.util.ArrayList<>(Collections.singletonList(
StringUtils.strip(role.getPermissionCode(), "[]")));
//将新数据添加至列表
list.addAll(codeList);
rolesPermission.setPermissionCode(list.toString());
rolesPermission.setId(role.getId());
result = permissionMapper.updateById(rolesPermission);
}else {
if (codeList!=null){
rolesPermission.setPermissionCode(codeList.toString());
}
result = permissionMapper.insert(rolesPermission);
if (role != null) {
result = updateRolePermission(rolesPermission, role, codeList);
} else {
result = insertRolePermission(rolesPermission, codeList);
}
return result > 0;
}
private RolesPermission getRoleByName(String roleName) {
return permissionMapper.selectOne(new QueryWrapper<RolesPermission>().eq(PermissionConstants.ROLE, roleName));
}
private int updateRolePermission(RolesPermission rolesPermission, RolesPermission role, List<String> codeList) {
//去掉头尾括号,并转为列表
List<String> list = new java.util.ArrayList<>(Collections.singletonList(
StringUtils.strip(role.getPermissionCode(), "[]")));
//将新数据添加至列表
list.addAll(codeList);
rolesPermission.setPermissionCode(list.toString());
rolesPermission.setId(role.getId());
return permissionMapper.updateById(rolesPermission);
}
private int insertRolePermission(RolesPermission rolesPermission, List<String> codeList) {
if (codeList != null) {
rolesPermission.setPermissionCode(codeList.toString());
}
return permissionMapper.insert(rolesPermission);
}
}

View File

@ -2,7 +2,7 @@ server:
port: 9092
spring:
application:
name: engine-jwt-manage
name: engine-auth
redis:
host: 115.159.33.152
port: 6379

View File

@ -1,13 +1,31 @@
package com.auth.server;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@SpringBootTest
class EtlAuthServerApplicationTests {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Test
void contextLoads() {
public void enCoder() {
String password="123";
String encode = bCryptPasswordEncoder.encode(password);
System.out.println("加密后的密码:"+encode);
}
@Test
public void matchesPassword(){
String encode="$2a$10$fEQQjl9rqSIWX/vHLy/LF.tovUIXInaR783YZXURMGMaUSIyefq4C";
boolean matches = bCryptPasswordEncoder.matches("123", encode);
if (matches){
System.out.println("密码正确");
}else {
System.out.println("密码错误");
}
}
}

View File

@ -2,7 +2,7 @@ server:
port: 9092
spring:
application:
name: engine-jwt-manage
name: engine-auth
redis:
host: 115.159.33.152
port: 6379

View File

@ -10,8 +10,7 @@
{
"name": "auth.jwt.enabled",
"type": "java.lang.Boolean",
"sourceType": "com.etl.jwt.config.AuthJwtProperties",
"defaultValue": true
"sourceType": "com.etl.jwt.config.AuthJwtProperties"
},
{
"name": "auth.jwt.expiration",
@ -27,8 +26,7 @@
"name": "auth.jwt.pwd-param-name",
"type": "java.lang.String",
"description": "用户登录-密码参数名称",
"sourceType": "com.etl.jwt.config.AuthJwtProperties",
"defaultValue": "password"
"sourceType": "com.etl.jwt.config.AuthJwtProperties"
},
{
"name": "auth.jwt.secret",
@ -43,15 +41,13 @@
{
"name": "auth.jwt.use-default-controller",
"type": "java.lang.Boolean",
"sourceType": "com.etl.jwt.config.AuthJwtProperties",
"defaultValue": false
"sourceType": "com.etl.jwt.config.AuthJwtProperties"
},
{
"name": "auth.jwt.user-param-name",
"type": "java.lang.String",
"description": "用户登录-用户名参数名称",
"sourceType": "com.etl.jwt.config.AuthJwtProperties",
"defaultValue": "userId"
"sourceType": "com.etl.jwt.config.AuthJwtProperties"
}
],
"hints": []