package com.gkhy.exam.framework.web.service; import cn.hutool.core.codec.Base64; import com.gkhy.exam.common.constant.CacheConstant; import com.gkhy.exam.common.constant.Constant; import com.gkhy.exam.common.constant.UserConstant; import com.gkhy.exam.common.domain.entity.SysUser; import com.gkhy.exam.common.domain.model.LoginBody; import com.gkhy.exam.common.domain.model.LoginUser; import com.gkhy.exam.common.domain.model.LoginUserDetails; import com.gkhy.exam.common.enums.LoginUserTagEnum; import com.gkhy.exam.common.exception.ApiException; import com.gkhy.exam.common.utils.IpUtils; import com.gkhy.exam.common.utils.RedisUtils; import com.gkhy.exam.framework.manager.AsyncManager; import com.gkhy.exam.framework.manager.factory.AsyncFactory; import com.gkhy.exam.framework.security.context.AuthenticationContextHolder; import com.gkhy.exam.system.domain.ExStudent; import com.gkhy.exam.system.service.ExStudentService; import com.gkhy.exam.system.service.SysUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; @Component public class SysLoginService { @Autowired private SysUserService sysUserService; @Autowired private SysPasswordService passwordService; @Resource private AuthenticationManager authenticationManager; @Autowired private TokenService tokenService; @Autowired private ExStudentService studentService; @Autowired private HttpServletRequest request; @Autowired private RedisUtils redisUtils; /** * 设置角色权限 * @param sysUser */ public void setRolePermission(SysUser sysUser){ } public void recordLoginInfo(Long userId,LoginUserTagEnum loginUserTagEnum){ if(loginUserTagEnum.getCode().equals(LoginUserTagEnum.ADMIN_USER.getCode())) { SysUser user = new SysUser(); user.setId(userId); user.setLoginIp(IpUtils.getIpAddr()); user.setLoginDate(LocalDateTime.now()); sysUserService.updateById(user); }else{ ExStudent student=new ExStudent(); student.setId(userId); student.setLoginIp(IpUtils.getIpAddr()); student.setLoginDate(LocalDateTime.now()); studentService.updateById(student); } } /** * 管理员用户登录 * @param loginBody * @return */ public LoginUser adminLogin(LoginBody loginBody) { String username=loginBody.getUsername(); String password=loginBody.getPassword(); password= Base64.decodeStr(password); //验证码校验 validateCaptcha(username,loginBody.getCode(),loginBody.getUuid()); loginPreCheck(username, password); Authentication authentication=null; try{ UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(username+LoginUserTagEnum.ADMIN_USER.getCode(),password); AuthenticationContextHolder.setContext(authenticationToken); // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername authentication = authenticationManager.authenticate(authenticationToken); LoginUserDetails loginUserDetails= (LoginUserDetails) authentication.getPrincipal(); passwordService.validate(loginUserDetails.getUser(),password); // AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_SUCCESS, "登录成功")); recordLoginInfo(loginUserDetails.getUser().getId(),LoginUserTagEnum.ADMIN_USER); return createLoginUser(loginUserDetails,LoginUserTagEnum.ADMIN_USER); }catch (Exception e){ if (e instanceof BadCredentialsException) { // AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_FAIL, "用户密码不匹配")); throw new ApiException("用户密码不匹配"); } else { // AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_FAIL, e.getMessage())); throw new ApiException(e.getMessage()); } }finally { AuthenticationContextHolder.clearContext(); } } /** * 学员用户登录 * @param loginBody * @return */ public LoginUser studentLogin(LoginBody loginBody) { String username=loginBody.getUsername(); String password=loginBody.getPassword(); password= Base64.decodeStr(password); loginPreCheck(username, password); Authentication authentication=null; try{ UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(username+LoginUserTagEnum.STUDENT_USER.getCode(),password); AuthenticationContextHolder.setContext(authenticationToken); // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername authentication = authenticationManager.authenticate(authenticationToken); LoginUserDetails loginUserDetails= (LoginUserDetails) authentication.getPrincipal(); passwordService.validate(loginUserDetails.getUser(),password); // AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_SUCCESS, "登录成功")); recordLoginInfo(loginUserDetails.getUser().getId(),LoginUserTagEnum.STUDENT_USER); return createLoginUser(loginUserDetails,LoginUserTagEnum.STUDENT_USER); }catch (Exception e){ if (e instanceof BadCredentialsException) { // AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_FAIL, "用户密码不匹配")); throw new ApiException("用户密码不匹配"); } else { // AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_FAIL, e.getMessage())); throw new ApiException(e.getMessage()); } }finally { AuthenticationContextHolder.clearContext(); } } private LoginUser createLoginUser(LoginUserDetails loginUserDetails,LoginUserTagEnum loginUserTagEnum){ LoginUser loginUser= new LoginUser() .setId(loginUserDetails.getUser().getId()) .setUsername(loginUserDetails.getUsername()) .setCompanyId(loginUserDetails.getUser().getCompanyId()); loginUser.setToken(tokenService.createToken(loginUserDetails.getUsername()+loginUserTagEnum.getCode())); tokenService.cacheUserToken(loginUserDetails.getUsername(),loginUser.getToken()); return loginUser; } /** * 登录前置校验 * @param username 用户名 * @param password 用户密码 */ public void loginPreCheck(String username, String password) { // 用户名或密码为空 错误 if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_FAIL, "用户名或者密码为空")); throw new ApiException("用户名或者密码为空"); } // 密码如果不在指定范围内 错误 if (password.length() < UserConstant.PASSWORD_MIN_LENGTH || password.length() > UserConstant.PASSWORD_MAX_LENGTH) { AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_FAIL, "密码长度不正确")); throw new ApiException("密码长度不正确"); } // 用户名不在指定范围内 错误 if (username.length() < UserConstant.USERNAME_MIN_LENGTH || username.length() > UserConstant.USERNAME_MAX_LENGTH) { AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_FAIL, "用户名长度不正确")); throw new ApiException("用户名长度不正确"); } // // IP黑名单校验 // String blackStr = configService.selectConfigByKey("sys.login.blackIPList"); // if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) // { // AsyncManager.me().execute(AsyncFactory.recordLoginInfo(username, Constant.LOGIN_FAIL, "访问IP已被列入系统黑名单")); // throw new ApiException("很遗憾,访问IP已被列入系统黑名单"); // } } /** * 校验验证码 * * @param username 用户名 * @param code 验证码 * @param uuid 唯一标识 * @return 结果 */ public void validateCaptcha(String username, String code, String uuid) { if(StringUtils.isBlank(code)||StringUtils.isBlank(uuid)){ throw new ApiException("验证码或验证码标识为空"); } String verifyKey = CacheConstant.CAPTCHA_CODE_KEY +uuid; String captcha = (String) redisUtils.get(verifyKey); redisUtils.del(verifyKey); if (StringUtils.isBlank(captcha)) { throw new ApiException("验证码已失效"); } if (!code.equalsIgnoreCase(captcha)) { throw new ApiException("验证码不正确"); } } public void logout(){ tokenService.delTokenCache(request); } }