/** * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng) *
* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.stylefeng.guns.sys.core.auth;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.stylefeng.guns.base.auth.context.LoginContextHolder;
import cn.stylefeng.guns.base.auth.exception.AuthException;
import cn.stylefeng.guns.base.auth.exception.enums.AuthExceptionEnum;
import cn.stylefeng.guns.base.auth.jwt.JwtTokenUtil;
import cn.stylefeng.guns.base.auth.jwt.payload.JwtPayLoad;
import cn.stylefeng.guns.base.auth.model.LoginUser;
import cn.stylefeng.guns.base.auth.service.AuthService;
import cn.stylefeng.guns.base.consts.ConstantsContext;
import cn.stylefeng.guns.base.tenant.context.DataBaseNameHolder;
import cn.stylefeng.guns.base.tenant.context.TenantCodeHolder;
import cn.stylefeng.guns.sys.core.auth.cache.SessionManager;
import cn.stylefeng.guns.sys.core.constant.factory.ConstantFactory;
import cn.stylefeng.guns.sys.core.constant.state.ManagerStatus;
import cn.stylefeng.guns.sys.core.listener.ConfigListener;
import cn.stylefeng.guns.sys.core.log.LogManager;
import cn.stylefeng.guns.sys.core.log.factory.LogTaskFactory;
import cn.stylefeng.guns.sys.core.util.SaltUtil;
import cn.stylefeng.guns.sys.modular.system.entity.User;
import cn.stylefeng.guns.sys.modular.system.factory.UserFactory;
import cn.stylefeng.guns.sys.modular.system.mapper.MenuMapper;
import cn.stylefeng.guns.sys.modular.system.mapper.UserMapper;
import cn.stylefeng.guns.sys.modular.system.service.DictService;
import cn.stylefeng.roses.core.util.HttpContext;
import cn.stylefeng.roses.core.util.SpringContextHolder;
import cn.stylefeng.roses.core.util.ToolUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import static cn.stylefeng.guns.base.consts.ConstantsContext.getJwtSecretExpireSec;
import static cn.stylefeng.guns.base.consts.ConstantsContext.getTokenHeaderName;
import static cn.stylefeng.roses.core.util.HttpContext.getIp;
@Service
@DependsOn("springContextHolder")
@Transactional(readOnly = true)
public class AuthServiceImpl implements AuthService {
@Autowired
private UserMapper userMapper;
@Autowired
private MenuMapper menuMapper;
@Autowired
private DictService dictService;
@Autowired
private SessionManager sessionManager;
public static AuthService me() {
return SpringContextHolder.getBean(AuthService.class);
}
@Override
public String login(String username, String password) {
User user = userMapper.getByAccount(username);
// 账号不存在
if (null == user) {
throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR);
}
//验证账号密码是否正确
String requestMd5 = SaltUtil.md5Encrypt(password, user.getSalt());
String dbMd5 = user.getPassword();
if (dbMd5 == null || !dbMd5.equalsIgnoreCase(requestMd5)) {
throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR);
}
return login(username);
}
@Override
public String login(String username) {
User user = userMapper.getByAccount(username);
// 账号不存在
if (null == user) {
throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR);
}
// 账号被冻结
if (!user.getStatus().equals(ManagerStatus.OK.getCode())) {
throw new AuthException(AuthExceptionEnum.ACCOUNT_FREEZE_ERROR);
}
//记录登录日志
LogManager.me().executeLog(LogTaskFactory.loginLog(user.getUserId(), getIp()));
//TODO key的作用
JwtPayLoad payLoad = new JwtPayLoad(user.getUserId(), user.getAccount(), "xxxx");
//创建token
String token = JwtTokenUtil.generateToken(payLoad);
//创建登录会话
sessionManager.createSession(token, user(username));
//创建cookie
addLoginCookie(token);
return token;
}
@Override
public void addLoginCookie(String token) {
//创建cookie
Cookie authorization = new Cookie(getTokenHeaderName(), token);
authorization.setMaxAge(getJwtSecretExpireSec().intValue());
authorization.setHttpOnly(true);
authorization.setPath("/");
HttpServletResponse response = HttpContext.getResponse();
response.addCookie(authorization);
}
@Override
public void logout() {
String token = LoginContextHolder.getContext().getToken();
logout(token);
}
@Override
public void logout(String token) {
//记录退出日志
LogManager.me().executeLog(LogTaskFactory.exitLog(LoginContextHolder.getContext().getUser().getId(), getIp()));
//删除Auth相关cookies
Cookie[] cookies = HttpContext.getRequest().getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
String tokenHeader = getTokenHeaderName();
if (tokenHeader.equalsIgnoreCase(cookie.getName())) {
Cookie temp = new Cookie(cookie.getName(), "");
temp.setMaxAge(0);
temp.setPath("/");
HttpContext.getResponse().addCookie(temp);
}
}
}
//删除会话
sessionManager.removeSession(token);
}
@Override
public LoginUser user(String account) {
User user = userMapper.getByAccount(account);
LoginUser loginUser = UserFactory.createLoginUser(user);
//用户角色数组
Long[] roleArray = Convert.toLongArray(user.getRoleId());
//如果角色是空就直接返回
if (roleArray == null || roleArray.length == 0) {
return loginUser;
}
//获取用户角色列表
List