package org.dromara.web.controller; import cn.dev33.satoken.annotation.SaIgnore; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.request.AuthRequest; import me.zhyd.oauth.utils.AuthStateUtils; import org.dromara.common.core.domain.AjaxResult; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.model.LoginBody; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.RegisterBody; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.MessageUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.social.config.properties.SocialLoginConfigProperties; import org.dromara.common.social.config.properties.SocialProperties; import org.dromara.common.social.utils.SocialUtils; import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.system.domain.SysClient; import org.dromara.system.domain.app.AppletLoginForm; import org.dromara.system.domain.bo.SysTenantBo; import org.dromara.system.domain.school.bo.SysSchoolNameBo; import org.dromara.system.domain.school.vo.SysSchoolNameVo; import org.dromara.system.domain.vo.SysRoleVo; import org.dromara.system.domain.vo.SysTenantVo; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.mapper.SysRoleMapper; import org.dromara.system.mapper.SysUserMapper; import org.dromara.system.service.*; import org.dromara.system.service.school.ISysSchoolNameService; import org.dromara.web.domain.vo.LoginTenantVo; import org.dromara.web.domain.vo.LoginVo; import org.dromara.web.domain.vo.TenantListVo; import org.dromara.web.service.IAuthStrategy; import org.dromara.web.service.SysLoginService; import org.dromara.web.service.SysRegisterService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 认证 * * @author Lion Li */ @Slf4j @SaIgnore @Validated @RequiredArgsConstructor @RestController @RequestMapping("/auth") public class AuthController { private final SocialProperties socialProperties; private final SysLoginService loginService; private final SysRegisterService registerService; private final ISysConfigService configService; private final ISysTenantService tenantService; private final ISysSocialService socialUserService; private final ISysClientService clientService; private final ISysSchoolNameService sysSchoolNameService; private final SysUserMapper sysUserMapper; private final SysRoleMapper sysRoleMapper; /** * 登录方法 * * @param loginBody 登录信息 * @return 结果 */ @PostMapping("/login") public R login(@Validated @RequestBody LoginBody loginBody) { // 授权类型和客户端id String clientId = loginBody.getClientId(); String grantType = loginBody.getGrantType(); SysClient client = clientService.queryByClientId(clientId); // 查询不到 client 或 client 内不包含 grantType if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) { log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType); return R.fail(MessageUtils.message("auth.grant.type.error")); } //去redis中查询当前账号登录租户id = loginBody.get Object tenantId = RedisUtils.getCacheObject(loginBody.getUsername() + ":login"); if (ObjectUtil.isEmpty(tenantId)) { tenantId = "000000"; //如果是空,则去查询 List sysUserVo = sysUserMapper.selectUserByUserNameList(loginBody.getUsername()); if (sysUserVo != null && sysUserVo.size() > 0) { boolean flag = true; for (SysUserVo userVo : sysUserVo) { if (!"000000".equals(userVo.getTenantId()) && flag){ tenantId = userVo.getTenantId(); } Long userId = userVo.getUserId(); List sysRoleVo = sysRoleMapper.selectRolePermissionByUserId(userId); for (SysRoleVo roleVo : sysRoleVo) { if ("teacher".equals(roleVo.getRoleKey())) { tenantId = userVo.getTenantId(); flag = false; break; } } } } } loginBody.setTenantId(tenantId.toString()); // 校验租户 loginService.checkTenant(loginBody.getTenantId()); // 登录 return R.ok(IAuthStrategy.login(loginBody, client)); } /** * 微信登录方法 * * @param form 登录信息 * @return 结果 */ @SaIgnore @PostMapping("/weChatLogin") public R weChatLogin(@Validated @RequestBody AppletLoginForm form) { LoginBody loginBody = new LoginBody(); String clientId = "428a8310cd442757ae699df5d894f051"; String grantType = "password"; loginBody.setClientId(clientId); loginBody.setGrantType(grantType); SysClient client = clientService.queryByClientId(clientId); // 查询不到 client 或 client 内不包含 grantType if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) { log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType); return R.fail(MessageUtils.message("auth.grant.type.error")); } LoginVo loginVo = IAuthStrategy.weChatLogin(form, loginBody, client); //去redis中查询当前账号登录租户id = loginBody.get Object tenantId = RedisUtils.getCacheObject(loginBody.getUsername() + ":login"); if (ObjectUtil.isEmpty(tenantId)) { //如果是空,则去查询 SysUserVo sysUserVo = sysUserMapper.selectUserByUserName(loginBody.getUsername()); tenantId = sysUserVo.getTenantId(); } loginBody.setTenantId(tenantId.toString()); // 校验租户 loginService.checkTenant(loginBody.getTenantId()); return R.ok(loginVo); } /** * 第三方登录请求 * * @param source 登录来源 * @return 结果 */ @GetMapping("/binding/{source}") public R authBinding(@PathVariable("source") String source) { SocialLoginConfigProperties obj = socialProperties.getType().get(source); if (ObjectUtil.isNull(obj)) { return R.fail(source + "平台账号暂不支持"); } AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties); String authorizeUrl = authRequest.authorize(AuthStateUtils.createState()); return R.ok("操作成功", authorizeUrl); } /** * 第三方登录回调业务处理 绑定授权 * * @param loginBody 请求体 * @return 结果 */ @PostMapping("/social/callback") public R socialCallback(@RequestBody LoginBody loginBody) { // 获取第三方登录信息 AuthResponse response = SocialUtils.loginAuth(loginBody, socialProperties); AuthUser authUserData = response.getData(); // 判断授权响应是否成功 if (!response.ok()) { return R.fail(response.getMsg()); } loginService.socialRegister(authUserData); return R.ok(); } /** * 取消授权 * * @param socialId socialId */ @DeleteMapping(value = "/unlock/{socialId}") public R unlockSocial(@PathVariable Long socialId) { Boolean rows = socialUserService.deleteWithValidById(socialId); return rows ? R.ok() : R.fail("取消授权失败"); } /** * 退出登录 */ @PostMapping("/logout") public R logout() { loginService.logout(); return R.ok("退出成功"); } /** * 用户注册 */ @PostMapping("/register") public R register(@Validated @RequestBody RegisterBody user) { if (!configService.selectRegisterEnabled(user.getTenantId())) { return R.fail("当前系统没有开启注册功能!"); } registerService.register(user); return R.ok(); } /** * 登录页面租户下拉框 * * @return 租户列表 */ @GetMapping("/tenant/list") public R tenantList(HttpServletRequest request) throws Exception { List tenantList = tenantService.queryList(new SysTenantBo()); List voList = MapstructUtils.convert(tenantList, TenantListVo.class); // 获取域名 String host; String referer = request.getHeader("referer"); if (StringUtils.isNotBlank(referer)) { // 这里从referer中取值是为了本地使用hosts添加虚拟域名,方便本地环境调试 host = referer.split("//")[1].split("/")[0]; } else { host = new URL(request.getRequestURL().toString()).getHost(); } // 根据域名进行筛选 List list = StreamUtils.filter(voList, vo -> StringUtils.equals(vo.getDomain(), host)); // 返回对象 LoginTenantVo vo = new LoginTenantVo(); vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList); vo.setTenantEnabled(TenantHelper.isEnable()); return R.ok(vo); } /** * 返回家长所在班级 * * @return 租户列表 */ @GetMapping("/parents/tenant/list") public R parentsTenantList(HttpServletRequest request) throws Exception { //查询账号的租户id LoginUser user = LoginHelper.getLoginUser(); List userList = sysUserMapper.selectUserListByUserName(user.getUsername()); List tList = new ArrayList<>(); for (SysUserVo sysUserVo : userList) { boolean bl = false; for (SysRoleVo role : sysUserVo.getRoles()) { if ("parents".equals(role.getRoleKey())) { bl = true; break; } } if (bl) { tList.add(sysUserVo.getTenantId()); } } SysTenantBo tenantBo = new SysTenantBo(); tenantBo.setTenantList(tList); List tenantList = tenantService.queryList(tenantBo); List voList = MapstructUtils.convert(tenantList, TenantListVo.class); // 返回对象 LoginTenantVo vo = new LoginTenantVo(); vo.setVoList(voList); vo.setTenantEnabled(TenantHelper.isEnable()); return R.ok(vo); } /** * 注册页获取学校下拉框 * * @return 租户列表 */ @GetMapping("/school/list") public AjaxResult schoolList() { List sysSchoolNameVos = sysSchoolNameService.queryList(new SysSchoolNameBo()); Map> collect = sysSchoolNameVos.parallelStream().collect(Collectors.groupingBy(SysSchoolNameVo::getInitial)); return AjaxResult.success(collect); } }