提交 | 用户 | 时间
|
e7c126
|
1 |
package com.iailab.module.system.controller.admin.auth; |
H |
2 |
|
|
3 |
import cn.hutool.core.collection.CollUtil; |
49b510
|
4 |
import cn.hutool.core.date.LocalDateTimeUtil; |
e7c126
|
5 |
import cn.hutool.core.util.StrUtil; |
H |
6 |
import com.iailab.framework.common.enums.CommonStatusEnum; |
|
7 |
import com.iailab.framework.common.enums.UserTypeEnum; |
|
8 |
import com.iailab.framework.common.pojo.CommonResult; |
7da8f1
|
9 |
import com.iailab.framework.common.util.object.BeanUtils; |
e7c126
|
10 |
import com.iailab.framework.security.config.SecurityProperties; |
ce910c
|
11 |
import com.iailab.framework.security.core.LoginUser; |
e7c126
|
12 |
import com.iailab.framework.security.core.util.SecurityFrameworkUtils; |
7da8f1
|
13 |
import com.iailab.module.system.controller.admin.app.vo.AppMenuRespVO; |
H |
14 |
import com.iailab.module.system.controller.admin.app.vo.AppRespVO; |
e7c126
|
15 |
import com.iailab.module.system.controller.admin.auth.vo.*; |
818a01
|
16 |
import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; |
7da8f1
|
17 |
import com.iailab.module.system.controller.admin.permission.vo.menu.MenuRespVO; |
e7c126
|
18 |
import com.iailab.module.system.convert.auth.AuthConvert; |
818a01
|
19 |
import com.iailab.module.system.dal.dataobject.app.AppDO; |
e7c126
|
20 |
import com.iailab.module.system.dal.dataobject.permission.MenuDO; |
H |
21 |
import com.iailab.module.system.dal.dataobject.permission.RoleDO; |
|
22 |
import com.iailab.module.system.dal.dataobject.user.AdminUserDO; |
|
23 |
import com.iailab.module.system.enums.logger.LoginLogTypeEnum; |
7da8f1
|
24 |
import com.iailab.module.system.enums.permission.MenuTypeEnum; |
818a01
|
25 |
import com.iailab.module.system.service.app.AppService; |
e7c126
|
26 |
import com.iailab.module.system.service.auth.AdminAuthService; |
H |
27 |
import com.iailab.module.system.service.permission.MenuService; |
|
28 |
import com.iailab.module.system.service.permission.PermissionService; |
|
29 |
import com.iailab.module.system.service.permission.RoleService; |
|
30 |
import com.iailab.module.system.service.social.SocialClientService; |
|
31 |
import com.iailab.module.system.service.user.AdminUserService; |
|
32 |
import io.swagger.v3.oas.annotations.Operation; |
|
33 |
import io.swagger.v3.oas.annotations.Parameter; |
|
34 |
import io.swagger.v3.oas.annotations.Parameters; |
|
35 |
import io.swagger.v3.oas.annotations.tags.Tag; |
|
36 |
import lombok.extern.slf4j.Slf4j; |
ce910c
|
37 |
import org.springframework.security.core.Authentication; |
e7c126
|
38 |
import org.springframework.validation.annotation.Validated; |
H |
39 |
import org.springframework.web.bind.annotation.*; |
|
40 |
|
|
41 |
import javax.annotation.Resource; |
|
42 |
import javax.annotation.security.PermitAll; |
|
43 |
import javax.servlet.http.HttpServletRequest; |
|
44 |
import javax.validation.Valid; |
7da8f1
|
45 |
import java.util.*; |
H |
46 |
import java.util.stream.Collectors; |
e7c126
|
47 |
|
H |
48 |
import static com.iailab.framework.common.pojo.CommonResult.success; |
|
49 |
import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet; |
ce910c
|
50 |
import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.*; |
818a01
|
51 |
import static com.iailab.framework.tenant.core.context.TenantContextHolder.getTenantId; |
e7c126
|
52 |
|
d9f9ba
|
53 |
|
e7c126
|
54 |
@Tag(name = "管理后台 - 认证") |
H |
55 |
@RestController |
|
56 |
@RequestMapping("/system/auth") |
|
57 |
@Validated |
|
58 |
@Slf4j |
|
59 |
public class AuthController { |
|
60 |
|
|
61 |
@Resource |
|
62 |
private AdminAuthService authService; |
|
63 |
@Resource |
|
64 |
private AdminUserService userService; |
|
65 |
@Resource |
|
66 |
private RoleService roleService; |
|
67 |
@Resource |
|
68 |
private MenuService menuService; |
|
69 |
@Resource |
|
70 |
private PermissionService permissionService; |
|
71 |
@Resource |
|
72 |
private SocialClientService socialClientService; |
|
73 |
@Resource |
|
74 |
private SecurityProperties securityProperties; |
818a01
|
75 |
@Resource |
H |
76 |
private AppService appService; |
e7c126
|
77 |
|
H |
78 |
@PostMapping("/login") |
|
79 |
@PermitAll |
|
80 |
@Operation(summary = "使用账号密码登录") |
|
81 |
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) { |
|
82 |
return success(authService.login(reqVO)); |
|
83 |
} |
|
84 |
|
|
85 |
@PostMapping("/logout") |
|
86 |
@PermitAll |
|
87 |
@Operation(summary = "登出系统") |
|
88 |
public CommonResult<Boolean> logout(HttpServletRequest request) { |
|
89 |
String token = SecurityFrameworkUtils.obtainAuthorization(request, |
|
90 |
securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); |
|
91 |
if (StrUtil.isNotBlank(token)) { |
|
92 |
authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType()); |
|
93 |
} |
|
94 |
return success(true); |
|
95 |
} |
|
96 |
|
|
97 |
@PostMapping("/refresh-token") |
|
98 |
@PermitAll |
|
99 |
@Operation(summary = "刷新令牌") |
|
100 |
@Parameter(name = "refreshToken", description = "刷新令牌", required = true) |
a7f2ca
|
101 |
public CommonResult<AuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken) { |
H |
102 |
return success(authService.refreshToken(refreshToken)); |
|
103 |
} |
|
104 |
|
|
105 |
@PostMapping("/client-refresh-token") |
|
106 |
@PermitAll |
|
107 |
@Operation(summary = "刷新令牌") |
|
108 |
@Parameter(name = "refreshToken", description = "刷新令牌", required = true) |
49b510
|
109 |
public Map<String, Object> refreshToken(@RequestParam("refreshToken") String refreshToken, @RequestParam("clientId") String clientId) { |
H |
110 |
AuthLoginRespVO authLoginRespVO = authService.refreshToken(refreshToken, clientId); |
|
111 |
Map<String, Object> map = new HashMap<>(); |
|
112 |
map.put("access_token", authLoginRespVO.getAccessToken()); |
|
113 |
map.put("refresh_token", authLoginRespVO.getRefreshToken()); |
|
114 |
map.put("expires_time", LocalDateTimeUtil.toEpochMilli(authLoginRespVO.getExpiresTime()) / 1000L); |
|
115 |
return map; |
e7c126
|
116 |
} |
H |
117 |
|
|
118 |
@GetMapping("/get-permission-info") |
|
119 |
@Operation(summary = "获取登录用户的权限信息") |
|
120 |
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() { |
|
121 |
// 1.1 获得用户信息 |
|
122 |
AdminUserDO user = userService.getUser(getLoginUserId()); |
|
123 |
if (user == null) { |
|
124 |
return success(null); |
|
125 |
} |
|
126 |
|
|
127 |
// 1.2 获得角色列表 |
|
128 |
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); |
|
129 |
if (CollUtil.isEmpty(roleIds)) { |
|
130 |
return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList())); |
|
131 |
} |
|
132 |
List<RoleDO> roles = roleService.getRoleList(roleIds); |
|
133 |
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 |
|
134 |
|
|
135 |
// 1.3 获得菜单列表 |
|
136 |
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); |
|
137 |
List<MenuDO> menuList = menuService.getMenuList(menuIds); |
d9f9ba
|
138 |
menuList = menuService.filterDisableMenus(menuList); |
355ca8
|
139 |
menuList = menuService.filterMenus(menuList, "system"); |
e7c126
|
140 |
|
H |
141 |
// 2. 拼接结果返回 |
|
142 |
return success(AuthConvert.INSTANCE.convert(user, roles, menuList)); |
|
143 |
} |
|
144 |
|
648b14
|
145 |
@GetMapping("/get-app-permission-info") |
H |
146 |
@Operation(summary = "脚手架获取登录用户的权限信息") |
|
147 |
public CommonResult<AuthPermissionInfoRespVO> getAppPermissionInfo() { |
|
148 |
// 1.1 获得用户信息 |
|
149 |
AdminUserDO user = userService.getUser(getLoginUserId()); |
|
150 |
if (user == null) { |
|
151 |
return success(null); |
|
152 |
} |
|
153 |
|
|
154 |
// 1.2 获得角色列表 |
|
155 |
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); |
|
156 |
if (CollUtil.isEmpty(roleIds)) { |
|
157 |
return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList())); |
|
158 |
} |
|
159 |
List<RoleDO> roles = roleService.getRoleList(roleIds); |
|
160 |
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 |
|
161 |
|
|
162 |
// 1.3 获得菜单列表 |
|
163 |
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); |
|
164 |
List<MenuDO> menuList = menuService.getMenuList(menuIds); |
|
165 |
menuList = menuService.filterDisableMenus(menuList); |
|
166 |
menuList = menuService.filterMenus(menuList, "app"); |
|
167 |
|
|
168 |
// 2. 拼接结果返回 |
|
169 |
return success(AuthConvert.INSTANCE.convert(user, roles, menuList)); |
|
170 |
} |
|
171 |
|
7da8f1
|
172 |
@GetMapping("/get-app-permission") |
818a01
|
173 |
@Operation(summary = "获取登录用户的app权限信息") |
7da8f1
|
174 |
public CommonResult<List<AppRespVO>> getAppPermission() { |
H |
175 |
List<AppRespVO> appList = new ArrayList<>(); |
818a01
|
176 |
// 1.1 获得用户信息 |
H |
177 |
AdminUserDO user = userService.getUser(getLoginUserId()); |
|
178 |
if (user == null) { |
|
179 |
return success(null); |
|
180 |
} |
|
181 |
// 1.2 获得角色列表 |
|
182 |
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); |
|
183 |
if (CollUtil.isEmpty(roleIds)) { |
7da8f1
|
184 |
return success(appList); |
818a01
|
185 |
} |
H |
186 |
List<RoleDO> roles = roleService.getRoleList(roleIds); |
|
187 |
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 |
|
188 |
|
|
189 |
// 1.3 获得应用菜单列表 |
|
190 |
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); |
|
191 |
List<MenuDO> menuList = menuService.getMenuList(menuIds); |
7da8f1
|
192 |
//只要一级菜单,一级菜单即是应用 |
H |
193 |
menuList = menuList.stream().filter(menu -> menu.getParentId() == 0l).collect(Collectors.toList()); |
818a01
|
194 |
menuList = menuService.filterDisableMenus(menuList); |
7da8f1
|
195 |
List<Long> ids = menuList.stream().map(MenuDO::getAppId).collect(Collectors.toList()); |
H |
196 |
List<AppDO> appDOS = appService.selectBatchIds(ids); |
|
197 |
//排序 |
|
198 |
Collections.sort(appDOS, Comparator.comparing(AppDO::getOrderNum)); |
818a01
|
199 |
// 2. 拼接结果返回 |
7da8f1
|
200 |
return success(BeanUtils.toBean(appDOS, AppRespVO.class)); |
H |
201 |
} |
|
202 |
|
|
203 |
@GetMapping("/get-app-menu-permission") |
|
204 |
@Operation(summary = "获取登录用户的app权限信息") |
|
205 |
public CommonResult<List<AuthPermissionInfoRespVO.MenuVO>> getAppMenuPermission(@RequestParam("id") Long id) { |
|
206 |
List<AuthPermissionInfoRespVO.MenuVO> menuVOS = new ArrayList<>(); |
|
207 |
// 1.1 获得用户信息 |
|
208 |
AdminUserDO user = userService.getUser(getLoginUserId()); |
|
209 |
if (user == null) { |
|
210 |
return success(null); |
|
211 |
} |
|
212 |
// 1.2 获得角色列表 |
|
213 |
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); |
|
214 |
if (CollUtil.isEmpty(roleIds)) { |
|
215 |
return success(menuVOS); |
|
216 |
} |
|
217 |
List<RoleDO> roles = roleService.getRoleList(roleIds); |
|
218 |
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 |
|
219 |
|
|
220 |
// 1.3 获得应用菜单列表 |
|
221 |
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); |
|
222 |
List<MenuDO> menuList = menuService.getMenuList(menuIds); |
|
223 |
menuList = menuService.filterDisableMenus(menuList); |
|
224 |
MenuDO menuDO = menuService.getMenuByAppId(id); |
ce910c
|
225 |
AppDO info = appService.getInfo(id); |
7da8f1
|
226 |
List<MenuDO> children = new LinkedList<>(); |
H |
227 |
// 遍历每一层 |
|
228 |
Collection<Long> parentIds = Collections.singleton(menuDO.getId()); |
|
229 |
for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下,存在死循环 |
|
230 |
// 查询当前层,所有的子应用菜单 |
|
231 |
List<MenuDO> menus = menuService.selectListByParentId(parentIds); |
|
232 |
// 1. 如果没有子菜单,则结束遍历 |
|
233 |
if (CollUtil.isEmpty(menus)) { |
|
234 |
break; |
|
235 |
} |
|
236 |
// 2. 如果有子应用菜单,继续遍历 |
|
237 |
children.addAll(menus); |
|
238 |
parentIds = convertSet(menus, MenuDO::getId); |
|
239 |
} |
|
240 |
children.retainAll(menuList); |
|
241 |
List<MenuDO> tempChildren = new LinkedList<>(); |
355ca8
|
242 |
//为每一个二级菜单(非外链菜单)增加一个隐藏父级目录 |
7da8f1
|
243 |
children.stream().forEach(menu -> { |
648b14
|
244 |
if (menu.getParentId().equals(menuDO.getId())) { |
H |
245 |
if(menu.getType().equals(MenuTypeEnum.MENU.getType())) { |
|
246 |
MenuDO parentMenu = BeanUtils.toBean(menu, MenuDO.class); |
|
247 |
parentMenu.setId(System.currentTimeMillis() + (int) (Math.random() * (99999 - 10000 + 1)) + 10000); |
|
248 |
parentMenu.setType(MenuTypeEnum.DIR.getType()); |
|
249 |
parentMenu.setVisible(true); |
|
250 |
parentMenu.setAlwaysShow(false); |
|
251 |
parentMenu.setParentId(menuDO.getId()); |
|
252 |
parentMenu.setPath("/"); |
|
253 |
menu.setParentId(parentMenu.getId()); |
|
254 |
tempChildren.add(parentMenu); |
|
255 |
} else if(menu.getType().equals(MenuTypeEnum.DIR.getType())) { |
|
256 |
// 为应用菜单二级目录前增加“/” |
355ca8
|
257 |
if(!menu.getPath().contains("http:") && !menu.getPath().contains("https:")) { |
H |
258 |
menu.setPath("/" + menu.getPath()); |
|
259 |
} |
648b14
|
260 |
} |
7da8f1
|
261 |
} |
648b14
|
262 |
tempChildren.add(menu); |
7da8f1
|
263 |
}); |
ce910c
|
264 |
menuVOS = AuthConvert.INSTANCE.buildMenuTree(tempChildren, menuDO.getId(), menuDO.getPath(), info.getType()); |
7da8f1
|
265 |
// 2. 拼接结果返回 |
H |
266 |
return success(menuVOS); |
818a01
|
267 |
} |
H |
268 |
|
e7c126
|
269 |
// ========== 短信登录相关 ========== |
H |
270 |
|
|
271 |
@PostMapping("/sms-login") |
|
272 |
@PermitAll |
|
273 |
@Operation(summary = "使用短信验证码登录") |
|
274 |
public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) { |
|
275 |
return success(authService.smsLogin(reqVO)); |
|
276 |
} |
|
277 |
|
|
278 |
@PostMapping("/send-sms-code") |
|
279 |
@PermitAll |
|
280 |
@Operation(summary = "发送手机验证码") |
|
281 |
public CommonResult<Boolean> sendLoginSmsCode(@RequestBody @Valid AuthSmsSendReqVO reqVO) { |
|
282 |
authService.sendSmsCode(reqVO); |
|
283 |
return success(true); |
|
284 |
} |
|
285 |
|
|
286 |
// ========== 社交登录相关 ========== |
|
287 |
|
|
288 |
@GetMapping("/social-auth-redirect") |
|
289 |
@PermitAll |
|
290 |
@Operation(summary = "社交授权的跳转") |
|
291 |
@Parameters({ |
|
292 |
@Parameter(name = "type", description = "社交类型", required = true), |
|
293 |
@Parameter(name = "redirectUri", description = "回调路径") |
|
294 |
}) |
|
295 |
public CommonResult<String> socialLogin(@RequestParam("type") Integer type, |
|
296 |
@RequestParam("redirectUri") String redirectUri) { |
|
297 |
return success(socialClientService.getAuthorizeUrl( |
|
298 |
type, UserTypeEnum.ADMIN.getValue(), redirectUri)); |
|
299 |
} |
|
300 |
|
|
301 |
@PostMapping("/social-login") |
|
302 |
@PermitAll |
|
303 |
@Operation(summary = "社交快捷登录,使用 code 授权码", description = "适合未登录的用户,但是社交账号已绑定用户") |
|
304 |
public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) { |
|
305 |
return success(authService.socialLogin(reqVO)); |
|
306 |
} |
|
307 |
|
|
308 |
} |