package com.gkhy.safePlatform.account.service.impl; import com.alibaba.fastjson.JSONArray; import com.gkhy.safePlatform.account.entity.enterprise.DepartmentInfoDO; import com.gkhy.safePlatform.account.entity.user.*; import com.gkhy.safePlatform.account.enums.RoleStatusEnum; import com.gkhy.safePlatform.account.enums.UserStatusEnum; import com.gkhy.safePlatform.account.model.dto.req.AccountPwdChangeReqDTO; import com.gkhy.safePlatform.account.service.AuthService; import com.gkhy.safePlatform.account.service.RedisService; import com.gkhy.safePlatform.account.service.baseService.*; import com.gkhy.safePlatform.account.utils.TokenUtil; import com.gkhy.safePlatform.account.utils.MenuUtil; import com.gkhy.safePlatform.account.utils.PasswordUtil; import com.gkhy.safePlatform.account.model.dto.req.LoginReqDTO; import com.gkhy.safePlatform.account.model.dto.resp.MenuRespDTO; import com.gkhy.safePlatform.account.model.dto.resp.UserLoginRespDTO; import com.gkhy.safePlatform.commons.co.ContextCacheUser; import com.gkhy.safePlatform.commons.enums.RedisKeyEnum; import com.gkhy.safePlatform.commons.enums.ResultCodes; import com.gkhy.safePlatform.commons.enums.UserTypeEnum; import com.gkhy.safePlatform.commons.exception.BusinessException; import com.gkhy.safePlatform.commons.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collections; import java.util.List; @Service("authService") public class AuthServiceImpl implements AuthService { @Autowired private UserInfoService userInfoService; @Autowired private RoleInfoService roleInfoService; @Autowired private PermissionInfoService permissionInfoService; @Autowired private MenuInfoService menuInfoService; @Autowired private TokenUtil tokenConfig; @Autowired private RedisService redisService; @Autowired private DepartmentInfoService departmentInfoService; @Autowired private PositionInfoService positionInfoService; /** * @Description: 登录 */ @Override public UserLoginRespDTO authLogin(LoginReqDTO loginParam) { // todo 根据入参判断用什么登录 String usernameParam = loginParam.getUsername(); // 用户名不能为空 if (StringUtils.isBlank(usernameParam)) { throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_USERNAME_NULL); } String username = usernameParam.trim(); UserInfo userDetail = userInfoService.getUserByUsername(username); // 用户不存在 if (userDetail == null) { throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_NOT_EXIST); } // 用户状态 以后可能会有离职、冻结等状态 if (!userDetail.getStatus().equals(UserStatusEnum.VALID.getCode())) { throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_NOT_EXIST); } // 密码不为空 if (StringUtils.isBlank(loginParam.getPassword())) { throw new BusinessException(ResultCodes.CLIENT_PASSWORD_NULL); } String password = loginParam.getPassword().trim(); // 密码匹配 if (!PasswordUtil.match(password, userDetail.getSalt(), userDetail.getHash())) { throw new BusinessException(ResultCodes.CLIENT_PASSWORD_ERROR); } // todo 用户过期 // 用户role 需要分配 RoleInfoDO roleInfo = roleInfoService.getRoleInfoDOById(userDetail.getRoleId()); if (roleInfo == null) { throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_HAS_NO_ROLE); } // 用户dep DepartmentInfoDO department = new DepartmentInfoDO(); if (userDetail.getDepId() != null) { department = departmentInfoService.getDepartmentInfoDOById(userDetail.getDepId()); } // 用户岗位 PositionInfoDO position = new PositionInfoDO(); if (userDetail.getPositionId() != null) { position = positionInfoService.getPositionInfoById(userDetail.getPositionId()); } // security对象中存入登陆者信息 List authorities = new ArrayList<>(); // role authorities.add(new SimpleGrantedAuthority("ROLE_"+ roleInfo.getCode())); // permission List permissions = this.getUserPermissionByUserId(userDetail.getUid()); for (PermissionInfo permission : permissions) { SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(permission.getCode()); authorities.add(simpleGrantedAuthority); } // 生成 accessToken String accessToken = TokenUtil.makeToken(username,userDetail.getUid()); // 存入 redis String accessTokenKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_TOKEN, userDetail.getUid()); String authoritiesKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_AUTHORITIES, userDetail.getUid()); ContextCacheUser contextCacheUser = new ContextCacheUser( // 用户uid userDetail.getUid(), // 用户基本信息 userDetail.getUsername(), userDetail.getRealName(), userDetail.getPhone(), userDetail.getEmail(), // 用户角色信息 roleInfo.getId(), roleInfo.getCode(), // 用户部门信息 department.getId(), department.getName(), // 用户岗位信息 position.getId(), position.getCode(), // 用户类型 userDetail.getType(), // token accessToken); // 1.通行认证:auth:token:access redisService.setCacheUserAndExpireTime(accessTokenKey, contextCacheUser, tokenConfig.getExpiration()); // 2.角色权限:auth:authorities redisService.setCacheAuthorityAndExpireTime(authoritiesKey, authorities, tokenConfig.getExpiration()); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetail, accessToken,authorities); SecurityContextHolder.getContext().setAuthentication(authenticationToken); return new UserLoginRespDTO( userDetail.getUid(), userDetail.getUsername(), userDetail.getRealName(), userDetail.getType(), userDetail.getStatus(), userDetail.getPhone(), userDetail.getEmail(), department.getName(), position.getName(), Collections.singletonList(roleInfo.getCode()), accessToken, department.getId() ); } @Override public List getUserPermissionByUserId(Long userId) { if (userId == null) { throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL); } return permissionInfoService.getPermissionsByUserId(userId); } @Override public UserInfo getUserInfoByUserId(Long userId) { if (userId == null) { throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL); } return userInfoService.getUserByUserId(userId); } /** * @Description: 根据用户名登出用户 */ @Override public void authLogout(Long userId) { assert userId != null; String accessTokenKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_TOKEN, userId); // 1.删除通行认证:auth:token:access redisService.cleanCacheUserByKey(accessTokenKey); // 2.删除用户权限 String authoritiesKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_AUTHORITIES, userId); redisService.cleanCacheAuthorityByKey(authoritiesKey); } @Override public UserInfo getUserByUserId(Long userId) { if (userId == null) { throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL); } return userInfoService.getUserByUserId(userId); } @Override public UserDetails getUserDetailsByUsername(String username) { return userInfoService.getUserByUsername(username); } @Override public void pwdChange(ContextCacheUser currentUser, AccountPwdChangeReqDTO reqDTO) { if (reqDTO.getUid() == null) { throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL); } if (StringUtils.isBlank(reqDTO.getNewPassword())) { throw new BusinessException(ResultCodes.CLIENT_PASSWORD_NULL); } String newPassword = reqDTO.getNewPassword().trim(); // todo 密码正则 UserInfo userInfo = userInfoService.getUserByUserId(reqDTO.getUid()); if (userInfo == null) { throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_NOT_EXIST); } if (!userInfo.getStatus().equals(UserStatusEnum.VALID.getCode())) { throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_NOT_EXIST); } String salt = PasswordUtil.makeSalt(); String hash = PasswordUtil.makePassword(newPassword, salt); userInfoService.updatePassword(reqDTO.getUid(), salt, hash); } @Override public RoleInfo getUserRoleByUserId(Long userId) { if (userId == null) { throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL); } RoleInfo roleInfo = roleInfoService.getRoleInfoByUserId(userId); if (roleInfo == null) { throw new BusinessException(ResultCodes.CLIENT_ROLE_NOT_EXIST); } assert roleInfo.getStatus() != null; RoleStatusEnum status = RoleStatusEnum.parse(roleInfo.getStatus()); if (status != RoleStatusEnum.ENABLED) { throw new BusinessException(ResultCodes.CLIENT_ROLE_CODE_NOT_ON); } return roleInfo; } @Override public List getUserMenuTreeByUserIdAndProjectId(ContextCacheUser currentUser, Long projectId){ if (currentUser.getUid() == null) { throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL); } // RoleInfo roleInfo = roleInfoService.getRoleInfoByUserId(currentUser.getUid()); // // 角色判断 // if (roleInfo == null) { // throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_HAS_NO_ROLE); // } List allMenu; // 1.redis获取所有菜单 String oo = redisService.getCacheMenuByKey(RedisKeyEnum.AUTH_MENU.getKey()); if (oo != null) { allMenu = JSONArray.parseArray(oo, MenuInfoDO.class); }else{ // 2.redis没有则mysql获取 allMenu = menuInfoService.getAllMenu(); redisService.setCacheMenuAndExpireTime(RedisKeyEnum.AUTH_MENU.getKey(), allMenu, tokenConfig.getExpiration()); } // // 如果project不为空 判断project是否为角色所拥有 // if (projectId != null) { // RoleProjectInfo roleProject = roleProjectInfoService.getRoleProjectInfo(roleInfo.getId(), projectId); // if (roleProject == null) { // // 需要返回公共页面 // return MenuUtil.generatePublicTree(allMenu); // } // } // 1.根据用户类型判断最高权限 // 1.1 type 为 admin的拥有最高菜单可分配和可视权限 不受角色code影响 List userMenu = allMenu; assert currentUser.getType() != null; if (!currentUser.getType().equals(UserTypeEnum.ADMIN.getCode())) { userMenu = MenuUtil.getUserMenuFromAllMenu(allMenu, currentUser.getRoleCode()); } return MenuUtil.generateMenuTree(userMenu, projectId); } }