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 jakarta.validation.constraints.NotBlank; import lombok.RequiredArgsConstructor; import me.zhyd.oauth.model.AuthCallback; 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.R; import org.dromara.common.core.domain.model.EmailLoginBody; import org.dromara.common.core.domain.model.LoginBody; import org.dromara.common.core.domain.model.RegisterBody; import org.dromara.common.core.domain.model.SmsLoginBody; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; 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.bo.SysTenantBo; import org.dromara.system.domain.vo.SysTenantVo; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.service.ISocialUserService; import org.dromara.system.service.ISysConfigService; import org.dromara.system.service.ISysTenantService; 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.SysLoginService; import org.dromara.web.service.SysRegisterService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.net.URL; import java.util.List; /** * 认证 * * @author Lion Li */ @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 ISocialUserService socialUserService; /** * 登录方法 * * @param body 登录信息 * @return 结果 */ @PostMapping("/login") public R login(@Validated @RequestBody LoginBody body) { LoginVo loginVo = new LoginVo(); // 生成令牌 String token = loginService.login( body.getTenantId(), body.getUsername(), body.getPassword(), body.getCode(), body.getUuid()); loginVo.setToken(token); return R.ok(loginVo); } /** * 短信登录 * * @param body 登录信息 * @return 结果 */ @PostMapping("/smsLogin") public R smsLogin(@Validated @RequestBody SmsLoginBody body) { LoginVo loginVo = new LoginVo(); // 生成令牌 String token = loginService.smsLogin( body.getTenantId(), body.getPhonenumber(), body.getSmsCode()); loginVo.setToken(token); return R.ok(loginVo); } /** * 邮件登录 * * @param body 登录信息 * @return 结果 */ @PostMapping("/emailLogin") public R emailLogin(@Validated @RequestBody EmailLoginBody body) { LoginVo loginVo = new LoginVo(); // 生成令牌 String token = loginService.emailLogin( body.getTenantId(), body.getEmail(), body.getEmailCode()); loginVo.setToken(token); return R.ok(loginVo); } /** * 小程序登录(示例) * * @param xcxCode 小程序code * @return 结果 */ @PostMapping("/xcxLogin") public R xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode) { LoginVo loginVo = new LoginVo(); // 生成令牌 String token = loginService.xcxLogin(xcxCode); loginVo.setToken(token); return R.ok(loginVo); } /** * 认证授权 * @param source */ @GetMapping("/binding/{source}") @ResponseBody public R authBinding(@PathVariable("source") String source, HttpServletRequest request){ SysUserVo userLoding = new SysUserVo(); if (ObjectUtil.isNull(userLoding)) { return R.fail("授权失败,请先登录再绑定"); } if (socialUserService.isExistByUserIdAndSource(userLoding.getUserId(),source)) { return R.fail(source + "平台账号已经被账号绑定"); } SocialLoginConfigProperties obj = socialProperties.getType().get(source); if (ObjectUtil.isNull(obj)){ return R.fail(source + "平台账号暂不支持"); } AuthRequest authRequest = SocialUtils.getAuthRequest(source, obj.getClientId(), obj.getClientSecret(), obj.getRedirectUri()); String authorizeUrl = authRequest.authorize(AuthStateUtils.createState()); return R.ok(authorizeUrl); } /** * 第三方登录回调业务处理 * @param source * @param callback * @param request * @return */ @SuppressWarnings("unchecked") @GetMapping("/social-login/{source}") public R socialLogin(@PathVariable("source") String source, AuthCallback callback, HttpServletRequest request) throws IOException { SocialLoginConfigProperties obj = socialProperties.getType().get(source); if (ObjectUtil.isNull(obj)){ return R.fail(source + "平台账号暂不支持"); } AuthRequest authRequest = SocialUtils.getAuthRequest(source, obj.getClientId(), obj.getClientSecret(), obj.getRedirectUri()); AuthResponse response = authRequest.login(callback); return loginService.socialLogin(source, response, request); } /** * 取消授权 * @param 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); } }