懒羊羊
2023-08-30 1ac2bc1590406d9babec036e154d8d08f34a6aa1
提交 | 用户 | 时间
1ac2bc 1 /**
2  * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng)
3  * <p>
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * <p>
8  * http://www.apache.org/licenses/LICENSE-2.0
9  * <p>
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package cn.stylefeng.guns.sys.core.auth;
17
18 import cn.hutool.core.collection.CollectionUtil;
19 import cn.hutool.core.convert.Convert;
20 import cn.stylefeng.guns.base.auth.context.LoginContextHolder;
21 import cn.stylefeng.guns.base.auth.exception.AuthException;
22 import cn.stylefeng.guns.base.auth.exception.enums.AuthExceptionEnum;
23 import cn.stylefeng.guns.base.auth.jwt.JwtTokenUtil;
24 import cn.stylefeng.guns.base.auth.jwt.payload.JwtPayLoad;
25 import cn.stylefeng.guns.base.auth.model.LoginUser;
26 import cn.stylefeng.guns.base.auth.service.AuthService;
27 import cn.stylefeng.guns.base.consts.ConstantsContext;
28 import cn.stylefeng.guns.base.tenant.context.DataBaseNameHolder;
29 import cn.stylefeng.guns.base.tenant.context.TenantCodeHolder;
30 import cn.stylefeng.guns.sys.core.auth.cache.SessionManager;
31 import cn.stylefeng.guns.sys.core.constant.factory.ConstantFactory;
32 import cn.stylefeng.guns.sys.core.constant.state.ManagerStatus;
33 import cn.stylefeng.guns.sys.core.listener.ConfigListener;
34 import cn.stylefeng.guns.sys.core.log.LogManager;
35 import cn.stylefeng.guns.sys.core.log.factory.LogTaskFactory;
36 import cn.stylefeng.guns.sys.core.util.SaltUtil;
37 import cn.stylefeng.guns.sys.modular.system.entity.User;
38 import cn.stylefeng.guns.sys.modular.system.factory.UserFactory;
39 import cn.stylefeng.guns.sys.modular.system.mapper.MenuMapper;
40 import cn.stylefeng.guns.sys.modular.system.mapper.UserMapper;
41 import cn.stylefeng.guns.sys.modular.system.service.DictService;
42 import cn.stylefeng.roses.core.util.HttpContext;
43 import cn.stylefeng.roses.core.util.SpringContextHolder;
44 import cn.stylefeng.roses.core.util.ToolUtil;
45 import org.springframework.beans.factory.annotation.Autowired;
46 import org.springframework.context.annotation.DependsOn;
47 import org.springframework.stereotype.Service;
48 import org.springframework.transaction.annotation.Transactional;
49
50 import javax.servlet.http.Cookie;
51 import javax.servlet.http.HttpServletRequest;
52 import javax.servlet.http.HttpServletResponse;
53 import java.util.*;
54
55 import static cn.stylefeng.guns.base.consts.ConstantsContext.getJwtSecretExpireSec;
56 import static cn.stylefeng.guns.base.consts.ConstantsContext.getTokenHeaderName;
57 import static cn.stylefeng.roses.core.util.HttpContext.getIp;
58
59 @Service
60 @DependsOn("springContextHolder")
61 @Transactional(readOnly = true)
62 public class AuthServiceImpl implements AuthService {
63
64     @Autowired
65     private UserMapper userMapper;
66
67     @Autowired
68     private MenuMapper menuMapper;
69
70     @Autowired
71     private DictService dictService;
72
73     @Autowired
74     private SessionManager sessionManager;
75
76     public static AuthService me() {
77         return SpringContextHolder.getBean(AuthService.class);
78     }
79
80     @Override
81     public String login(String username, String password) {
82
83         User user = userMapper.getByAccount(username);
84
85         // 账号不存在
86         if (null == user) {
87             throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR);
88         }
89
90         //验证账号密码是否正确
91         String requestMd5 = SaltUtil.md5Encrypt(password, user.getSalt());
92         String dbMd5 = user.getPassword();
93         if (dbMd5 == null || !dbMd5.equalsIgnoreCase(requestMd5)) {
94             throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR);
95         }
96
97         return login(username);
98     }
99
100     @Override
101     public String login(String username) {
102
103         User user = userMapper.getByAccount(username);
104
105         // 账号不存在
106         if (null == user) {
107             throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR);
108         }
109
110         // 账号被冻结
111         if (!user.getStatus().equals(ManagerStatus.OK.getCode())) {
112             throw new AuthException(AuthExceptionEnum.ACCOUNT_FREEZE_ERROR);
113         }
114
115         //记录登录日志
116         LogManager.me().executeLog(LogTaskFactory.loginLog(user.getUserId(), getIp()));
117
118         //TODO key的作用
119         JwtPayLoad payLoad = new JwtPayLoad(user.getUserId(), user.getAccount(), "xxxx");
120
121         //创建token
122         String token = JwtTokenUtil.generateToken(payLoad);
123
124         //创建登录会话
125         sessionManager.createSession(token, user(username));
126
127         //创建cookie
128         addLoginCookie(token);
129
130         return token;
131     }
132
133     @Override
134     public void addLoginCookie(String token) {
135         //创建cookie
136         Cookie authorization = new Cookie(getTokenHeaderName(), token);
137         authorization.setMaxAge(getJwtSecretExpireSec().intValue());
138         authorization.setHttpOnly(true);
139         authorization.setPath("/");
140         HttpServletResponse response = HttpContext.getResponse();
141         response.addCookie(authorization);
142     }
143
144     @Override
145     public void logout() {
146         String token = LoginContextHolder.getContext().getToken();
147         logout(token);
148     }
149
150     @Override
151     public void logout(String token) {
152
153         //记录退出日志
154         LogManager.me().executeLog(LogTaskFactory.exitLog(LoginContextHolder.getContext().getUser().getId(), getIp()));
155
156         //删除Auth相关cookies
157         Cookie[] cookies = HttpContext.getRequest().getCookies();
158         if (cookies != null) {
159             for (Cookie cookie : cookies) {
160                 String tokenHeader = getTokenHeaderName();
161                 if (tokenHeader.equalsIgnoreCase(cookie.getName())) {
162                     Cookie temp = new Cookie(cookie.getName(), "");
163                     temp.setMaxAge(0);
164                     temp.setPath("/");
165                     HttpContext.getResponse().addCookie(temp);
166                 }
167             }
168         }
169
170         //删除会话
171         sessionManager.removeSession(token);
172     }
173
174     @Override
175     public LoginUser user(String account) {
176
177         User user = userMapper.getByAccount(account);
178
179         LoginUser loginUser = UserFactory.createLoginUser(user);
180
181         //用户角色数组
182         Long[] roleArray = Convert.toLongArray(user.getRoleId());
183
184         //如果角色是空就直接返回
185         if (roleArray == null || roleArray.length == 0) {
186             return loginUser;
187         }
188
189         //获取用户角色列表
190         List<Long> roleList = new ArrayList<>();
191         List<String> roleNameList = new ArrayList<>();
192         List<String> roleTipList = new ArrayList<>();
193         for (Long roleId : roleArray) {
194             roleList.add(roleId);
195             roleNameList.add(ConstantFactory.me().getSingleRoleName(roleId));
196             roleTipList.add(ConstantFactory.me().getSingleRoleTip(roleId));
197         }
198         loginUser.setRoleList(roleList);
199         loginUser.setRoleNames(roleNameList);
200         loginUser.setRoleTips(roleTipList);
201
202         //根据角色获取系统的类型
203         List<String> systemTypes = this.menuMapper.getMenusTypesByRoleIds(roleList);
204
205         //通过字典编码
206         List<Map<String, Object>> dictsByCodes = dictService.getDictsByCodes(systemTypes);
207         loginUser.setSystemTypes(dictsByCodes);
208
209         //设置权限列表
210         Set<String> permissionSet = new HashSet<>();
211         for (Long roleId : roleList) {
212             List<String> permissions = this.findPermissionsByRoleId(roleId);
213             if (permissions != null) {
214                 for (String permission : permissions) {
215                     if (ToolUtil.isNotEmpty(permission)) {
216                         permissionSet.add(permission);
217                     }
218                 }
219             }
220         }
221         loginUser.setPermissions(permissionSet);
222
223         //如果开启了多租户功能,则设置当前登录用户的租户标识
224         if (ConstantsContext.getTenantOpen()) {
225             String tenantCode = TenantCodeHolder.get();
226             String dataBaseName = DataBaseNameHolder.get();
227             if (ToolUtil.isNotEmpty(tenantCode) && ToolUtil.isNotEmpty(dataBaseName)) {
228                 loginUser.setTenantCode(tenantCode);
229                 loginUser.setTenantDataSourceName(dataBaseName);
230             }
231
232             //注意,这里remove不代表所有情况,在aop remove
233             TenantCodeHolder.remove();
234             DataBaseNameHolder.remove();
235         }
236
237         return loginUser;
238     }
239
240     @Override
241     public List<String> findPermissionsByRoleId(Long roleId) {
242         return menuMapper.getResUrlsByRoleId(roleId);
243     }
244
245     @Override
246     public boolean check(String[] roleNames) {
247         LoginUser user = LoginContextHolder.getContext().getUser();
248         if (null == user) {
249             return false;
250         }
251         ArrayList<String> objects = CollectionUtil.newArrayList(roleNames);
252         String join = CollectionUtil.join(objects, ",");
253         if (LoginContextHolder.getContext().hasAnyRoles(join)) {
254             return true;
255         }
256         return false;
257     }
258
259     @Override
260     public boolean checkAll() {
261         HttpServletRequest request = HttpContext.getRequest();
262         LoginUser user = LoginContextHolder.getContext().getUser();
263         if (null == user) {
264             return false;
265         }
266         String requestURI = request.getRequestURI().replaceFirst(ConfigListener.getConf().get("contextPath"), "");
267         String[] str = requestURI.split("/");
268         if (str.length > 3) {
269             requestURI = "/" + str[1] + "/" + str[2];
270         }
271         if (LoginContextHolder.getContext().hasPermission(requestURI)) {
272             return true;
273         }
274         return false;
275     }
276
277 }