| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- package jnpf.controller;
- import cn.hutool.core.collection.CollectionUtil;
- import cn.hutool.core.net.url.UrlBuilder;
- import cn.hutool.core.text.StrPool;
- import io.swagger.v3.oas.annotations.Operation;
- import io.swagger.v3.oas.annotations.Parameter;
- import io.swagger.v3.oas.annotations.Parameters;
- import io.swagger.v3.oas.annotations.tags.Tag;
- import jnpf.base.ActionResult;
- import jnpf.base.UserInfo;
- import jnpf.base.service.SysconfigService;
- import jnpf.config.ConfigValueUtil;
- import jnpf.config.JnpfOauthConfig;
- import jnpf.constant.JnpfConst;
- import jnpf.constant.MsgCode;
- import jnpf.constant.PermissionConst;
- import jnpf.consts.AuthConsts;
- import jnpf.consts.DeviceType;
- import jnpf.consts.LoginTicketStatus;
- import jnpf.consts.ScanCodeTicketStatus;
- import jnpf.database.util.TenantDataSourceUtil;
- import jnpf.exception.LoginException;
- import jnpf.granter.TokenGranter;
- import jnpf.granter.TokenGranterBuilder;
- import jnpf.granter.UserDetailsServiceBuilder;
- import jnpf.model.*;
- import jnpf.model.login.MeInfoVO;
- import jnpf.model.login.PcUserVO;
- import jnpf.model.login.UserSystemVO;
- import jnpf.model.logout.LogoutResultModel;
- import jnpf.permission.controller.SocialsUserController;
- import jnpf.permission.entity.UserEntity;
- import jnpf.permission.model.socails.SocialsUserVo;
- import jnpf.permission.service.UserService;
- import jnpf.service.AuthService;
- import jnpf.service.LogService;
- import jnpf.service.LoginService;
- import jnpf.util.*;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
- import java.io.IOException;
- import java.util.*;
- import static jnpf.consts.AuthConsts.PARAMS_JNPF_TICKET;
- /**
- * 登录控制器
- *
- * @author JNPF开发平台组
- * @version V3.1.0
- * @copyright 引迈信息技术有限公司
- * @date 2019年9月26日 上午9:18
- */
- @Tag(name = "登陆数据", description = "oauth")
- @Slf4j
- @RestController
- @RequestMapping("/api/oauth")
- public class LoginController {
- @Autowired
- private UserService userApi;
- @Autowired
- private LoginService loginService;
- @Autowired
- private AuthService authService;
- @Autowired
- private ConfigValueUtil configValueUtil;
- @Autowired
- private JnpfOauthConfig oauthConfig;
- @Autowired
- private SysconfigService sysConfigApi;
- @Autowired
- private RedisUtil redisUtil;
- @Autowired
- private TokenGranterBuilder tokenGranterBuilder;
- @Autowired
- private SocialsUserController socialsUserApi;
- @Autowired
- private UserDetailsServiceBuilder userDetailsServiceBuilder;
- @Autowired
- private LogService logApi;
- /**
- * 登陆
- *
- * @param parameters 登录参数
- * @return
- * @throws LoginException 登录异常
- */
- @NoDataSourceBind
- @Operation(summary = "登陆")
- @Parameters({
- @Parameter(name = "parameters", description = "登录参数", required = true)
- })
- @RequestMapping(value = "/Login/**", method = {RequestMethod.GET, RequestMethod.POST})
- public ActionResult<LoginVO> login(@RequestParam Map<String, String> parameters) throws LoginException {
- return authService.login(parameters);
- }
- /**
- * 验证密码
- *
- * @param loginForm 登录模型
- * @return
- * @throws LoginException 登录异常
- */
- @Operation(summary = "锁屏解锁登录")
- @Parameters({
- @Parameter(name = "loginForm", description = "登录模型", required = true)
- })
- @PostMapping("/LockScreen")
- public ActionResult lockScreen(@RequestBody LoginForm loginForm) throws LoginException {
- UserEntity userEntity = userApi.getUserByAccount(loginForm.getAccount());
- if (userEntity == null) {
- UserInfo userInfo = UserProvider.getUser();
- if (userInfo.getUserId() != null) {
- UserProvider.logoutByUserId(userInfo.getUserId());
- }
- throw new LoginException(MsgCode.FA001.get());
- }
- if (!Md5Util.getStringMd5(loginForm.getPassword().toLowerCase() + userEntity.getSecretkey().toLowerCase()).equals(userEntity.getPassword())) {
- throw new LoginException(MsgCode.OA020.get());
- }
- return ActionResult.success(MsgCode.SU005.get());
- }
- /**
- * 登录注销
- *
- * @param grandtype 登录类型
- * @return
- */
- @NoDataSourceBind
- @Operation(summary = "退出")
- @Parameters({
- @Parameter(name = "grandtype", description = "登录类型", required = true)
- })
- @RequestMapping(value = {"/Logout", "/Logout/{grandtype}"}, method = {RequestMethod.GET, RequestMethod.POST})
- public ActionResult<LogoutResultModel> logout(@PathVariable(value = "grandtype", required = false) String grandtype) {
- long millis = System.currentTimeMillis();
- TokenGranter tokenGranter = tokenGranterBuilder.getGranterByLogin(grandtype);
- if (tokenGranter != null) {
- UserInfo userInfo = UserProvider.getUser();
- logApi.writeLogAsync(userInfo.getUserId(), userInfo.getUserName() + "/" + userInfo.getUserAccount(), "退出登录", userInfo, 1, 1, (System.currentTimeMillis() - millis));
- return tokenGranter.logout();
- }
- return ActionResult.success();
- }
- /**
- * 踢出指定用户, 推送Websocket用户被强制下线
- *
- * @param tokens token集合
- * @param userId 租户id
- * @param tenantId 租户id
- */
- @NoDataSourceBind
- @Operation(summary = "踢出指定用户")
- @Parameters({
- @Parameter(name = "tokens", description = "token集合"),
- @Parameter(name = "userId", description = "租户id"),
- @Parameter(name = "tenantId", description = "租户id"),
- })
- @PostMapping(value = {"/KickoutToken"})
- public void kickoutByToken(@RequestParam(value = "tokens", required = false) String[] tokens, @RequestParam(name = "userId", required = false) String userId, @RequestParam(name = "tenantId", required = false) String tenantId) {
- if (StringUtil.isNotEmpty(tokens)) {
- authService.kickoutByToken(tokens);
- } else {
- authService.kickoutByUserId(userId, tenantId);
- }
- }
- /**
- * 获取用户登录信息
- *
- * @param type Web/App
- * @return
- * @throws LoginException 登录异常
- */
- @Operation(summary = "获取用户登录信息")
- @Parameters({
- @Parameter(name = "type", description = "Web/App")
- })
- @GetMapping("/CurrentUser")
- public ActionResult<PcUserVO> currentUser(String type, String systemCode, @RequestParam(value = "isBackend", required = false) Integer isBackend) throws LoginException {
- type = StringUtil.isEmpty(type) ? JnpfConst.WEB : JnpfConst.APP;
- if (!Objects.equals(isBackend, 1)) {
- isBackend = 0;
- }
- UserInfo userInfo = UserProvider.getUser();
- if (DeviceType.TEMPUSERLIMITED.getDevice().equals(userInfo.getLoginDevice())) {
- throw new LoginException(MsgCode.OA022.get());
- }
- PcUserVO pcUserVO = loginService.getCurrentUser(type, systemCode, isBackend);
- if (pcUserVO == null) {
- throw new LoginException(MsgCode.LOG001.get());
- }
- //自动切身份
- if (StringUtil.isEmpty(pcUserVO.getCurrentSystemId()) && JnpfConst.APP.equals(type)
- && CollectionUtil.isNotEmpty(pcUserVO.getUserInfo().getStandingList())) {
- List<UserSystemVO> standingList = pcUserVO.getUserInfo().getStandingList();
- //先切使用者
- UserSystemVO userSystemVO = standingList.stream().filter(t -> PermissionConst.USER.equals(t.getEnCode())).findFirst().orElse(null);
- if (userSystemVO != null) {
- UserEntity user = new UserEntity();
- user.setId(userInfo.getUserId());
- user.setAppStanding(userSystemVO.getId());
- boolean update = userApi.updateById(user);
- if (update) {
- pcUserVO = loginService.getCurrentUser(type, systemCode, isBackend);
- }
- }
- //没有使用者遍历其他身份
- if (userSystemVO == null || StringUtil.isEmpty(pcUserVO.getCurrentSystemId())) {
- for (UserSystemVO standVo : standingList) {
- if (!standVo.isCurrentStanding()) {
- UserEntity user = new UserEntity();
- user.setId(userInfo.getUserId());
- user.setAppStanding(standVo.getId());
- boolean update = userApi.updateById(user);
- if (update) {
- pcUserVO = loginService.getCurrentUser(type, systemCode, isBackend);
- }
- if (!StringUtil.isEmpty(pcUserVO.getCurrentSystemId())) break;
- }
- }
- }
- //身份切换后还是没有系统报错
- if (StringUtil.isEmpty(pcUserVO.getCurrentSystemId())) {
- throw new LoginException(MsgCode.LOG004.get());
- }
- }
- pcUserVO.setCurrentSystemId(null);
- //当前身份没有菜单信息时,直接提示权限不足
- if (pcUserVO.getMenuList().isEmpty() && StringUtil.isNotEmpty(systemCode)) {
- throw new LoginException(MsgCode.LOG004.get());
- }
- //app没有身份和权限的时候直接退出
- if (JnpfConst.APP.equals(type)
- && CollectionUtil.isEmpty(pcUserVO.getUserInfo().getStandingList())
- && pcUserVO.getMenuList().isEmpty()) {
- userApi.logoutUser(MsgCode.LOG004.get(), Arrays.asList(userInfo.getUserId()));
- }
- return ActionResult.success(pcUserVO);
- }
- /**
- * 修改密码信息发送
- */
- @Operation(summary = "修改密码信息发送")
- @PostMapping("/updatePasswordMessage")
- public ActionResult updatePasswordMessage() {
- loginService.updatePasswordMessage();
- return ActionResult.success();
- }
- /**
- * 图形验证码
- *
- * @param codeLength 验证码长度
- * @param timestamp 验证码标识
- */
- @NoDataSourceBind()
- @Operation(summary = "图形验证码")
- @Parameters({
- @Parameter(name = "codeLength", description = "验证码长度", required = true),
- @Parameter(name = "timestamp", description = "验证码标识", required = true)
- })
- @GetMapping("/ImageCode/{codeLength}/{timestamp}")
- public void imageCode(@PathVariable("codeLength") Integer codeLength, @PathVariable("timestamp") String timestamp) {
- DownUtil.downCode(codeLength);
- redisUtil.insert(timestamp, ServletUtil.getSession().getAttribute(CodeUtil.RANDOMCODEKEY), 300);
- }
- /**
- * 注销用户
- *
- * @return
- */
- @Operation(summary = "注销用户")
- @PostMapping("/logoutCurrentUser")
- public ActionResult logoutCurrentUser() {
- UserInfo userInfo = UserProvider.getUser();
- if (userInfo.getIsAdministrator() != null && UserProvider.getUser().getIsAdministrator()) {
- return ActionResult.fail(MsgCode.OA023.get());
- }
- if (userInfo.getIsAdministrator() != null) {
- if (!userInfo.getIsAdministrator()) {
- userApi.delete(userApi.getInfo(userInfo.getUserId()));
- UserProvider.kickoutByUserId(userInfo.getUserId(), userInfo.getTenantId());
- }
- }
- return ActionResult.success(MsgCode.SU005.get());
- }
- /**
- * 判断是否需要验证码
- *
- * @param account 账号
- */
- @NoDataSourceBind()
- @Operation(summary = "判断是否需要验证码")
- @Parameters({
- @Parameter(name = "account", description = "账号", required = true)
- })
- @GetMapping("/getConfig/{account}")
- public ActionResult<LoginModel> check(@PathVariable("account") String account) throws LoginException {
- LoginModel loginModel = new LoginModel();
- if (configValueUtil.isMultiTenancy()) {
- LoginForm loginForm = new LoginForm();
- loginForm.setAccount(account);
- UserInfo userInfo = new UserInfo();
- userInfo.setUserAccount(loginForm.getAccount());
- userInfo = loginService.getTenantAccount(userInfo);
- }
- // 获取配置
- BaseSystemInfo sysConfigInfo = sysConfigApi.getSysInfo();
- // 是否开启验证码
- if (Objects.nonNull(sysConfigInfo) && "1".equals(String.valueOf(sysConfigInfo.getEnableVerificationCode()))) {
- loginModel.setEnableVerificationCode(1);
- Integer verificationCodeNumber = sysConfigInfo.getVerificationCodeNumber();
- loginModel.setVerificationCodeNumber(verificationCodeNumber == null ? 4 : verificationCodeNumber);
- return ActionResult.success(loginModel);
- }
- loginModel.setEnableVerificationCode(0);
- return ActionResult.success(loginModel);
- }
- /**
- * 获取登录配置, 是否需要跳转、第三方登录信息
- *
- * @return {re}
- * @throws LoginException 登录异常
- */
- @NoDataSourceBind()
- @Operation(summary = "获取登录配置")
- @GetMapping("/getLoginConfig")
- public ActionResult<LoginConfigModel> getLoginConfig() {
- LoginConfigModel loginConfigModel = new LoginConfigModel();
- if (oauthConfig.getSsoEnabled()) {
- String url = oauthConfig.getLoginPath() + StrPool.SLASH + oauthConfig.getDefaultSSO();
- loginConfigModel.setRedirect(true);
- loginConfigModel.setUrl(url);
- loginConfigModel.setTicketParams(PARAMS_JNPF_TICKET);
- } else {
- //追加第三方登录配置
- List<SocialsUserVo> loginList = socialsUserApi.getLoginList(PARAMS_JNPF_TICKET.toUpperCase());
- if (CollectionUtil.isNotEmpty(loginList)) {
- loginConfigModel.setSocialsList(loginList);
- loginConfigModel.setRedirect(false);
- loginConfigModel.setTicketParams(PARAMS_JNPF_TICKET);
- }
- }
- return ActionResult.success(loginConfigModel);
- }
- /**
- * 获取登录票据
- *
- * @return {msg:有效期, data:票据}
- */
- @NoDataSourceBind()
- @Operation(summary = "获取登录票据")
- @GetMapping("/getTicket")
- public ActionResult<String> getTicket() {
- LoginTicketModel ticketModel = new LoginTicketModel();
- ticketModel.setTicketTimeout(System.currentTimeMillis() + oauthConfig.getTicketTimeout() * 1000);
- String ticket = TicketUtil.createTicket(ticketModel, oauthConfig.getTicketTimeout());
- return ActionResult.success(ticketModel.getTicketTimeout().toString(), ticket);
- }
- /**
- * 检测票据登录状态
- *
- * @return {re}
- * @throws LoginException
- */
- @NoDataSourceBind()
- @Operation(summary = "获取登录状态")
- @GetMapping("/getTicketStatus/{ticket}")
- public ActionResult<LoginTicketModel> getTicketStatus(@PathVariable("ticket") String ticket) {
- LoginTicketModel ticketModel = TicketUtil.parseTicket(ticket);
- if (ticketModel == null) {
- ticketModel = new LoginTicketModel().setStatus(LoginTicketStatus.Invalid.getStatus()).setValue("票据失效!");
- } else {
- if (ticketModel.getStatus() != LoginTicketStatus.UnLogin.getStatus()
- && ticketModel.getStatus() != LoginTicketStatus.UnBind.getStatus()
- && ticketModel.getStatus() != LoginTicketStatus.UnBindMes.getStatus()
- && ticketModel.getStatus() != LoginTicketStatus.Multitenancy.getStatus()) {
- TicketUtil.deleteTicket(ticket);
- }
- }
- return ActionResult.success(ticketModel);
- }
- /**
- * 官网重置密码专用
- *
- * @return
- */
- @NoDataSourceBind()
- @Operation(summary = "官网重置密码专用")
- @GetMapping("/resetOfficialPassword/{mobile}/{code}")
- public ActionResult resetOfficialPassword(@PathVariable("mobile") String mobile, @PathVariable("code") String code) throws LoginException {
- //校验验证码
- TenantDataSourceUtil.checkOfficialSmsCode(mobile, code, 2);
- //切换租户
- LoginForm loginForm = new LoginForm();
- loginForm.setAccount(mobile);
- UserInfo userInfo = new UserInfo();
- userInfo.setUserAccount(loginForm.getAccount());
- try {
- userInfo = loginService.getTenantAccount(userInfo);
- } catch (Exception e) {
- return ActionResult.fail(MsgCode.LOG105.get());
- }
- // 重置密码 123456
- UserEntity userEntity = userDetailsServiceBuilder.getUserDetailService(AuthConsts.USERDETAIL_ACCOUNT).loadUserEntity(userInfo);
- userEntity.setPassword("e10adc3949ba59abbe56e057f20f883e");
- userEntity.setPassword(Md5Util.getStringMd5(userEntity.getPassword().toLowerCase() + userEntity.getSecretkey().toLowerCase()));
- boolean result = userApi.updateById(userEntity);
- if (result) {
- return ActionResult.success(MsgCode.LOG205.get());
- } else {
- return ActionResult.fail(MsgCode.LOG206.get());
- }
- }
- /**
- * 生成扫码凭证
- *
- * @return
- */
- @NoDataSourceBind()
- @Operation(summary = "生成扫码凭证")
- @GetMapping("/codeCertificate")
- public ActionResult codeCertificate() throws LoginException {
- ScanCodeLoginConfigModel ticketModel = new ScanCodeLoginConfigModel();
- ticketModel.setTicketTimeout(System.currentTimeMillis() + configValueUtil.getCodeCertificateTimeout() * 1000);
- String ticket = TicketUtil.createTicket(ticketModel, configValueUtil.getCodeCertificateTimeout());
- return ActionResult.success(ticketModel.getTicketTimeout().toString(), ticket);
- }
- /**
- * 获取扫码凭证状态
- *
- * @param ticket
- * @return
- * @throws LoginException
- */
- @NoDataSourceBind()
- @Operation(summary = "获取扫码凭证状态")
- @GetMapping("/codeCertificateStatus/{ticket}")
- public ActionResult codeCertificateStatus(@PathVariable("ticket") String ticket) throws LoginException {
- ScanCodeLoginConfigModel ticketModel = TicketUtil.parseTicket(ticket);
- if (ticketModel == null) {
- ticketModel = new ScanCodeLoginConfigModel();
- ticketModel.setStatus(ScanCodeTicketStatus.Invalid.getStatus());
- }
- return ActionResult.success(ticketModel);
- }
- /**
- * 确认登录
- *
- * @param ticket
- * @return
- * @throws LoginException
- */
- @NoDataSourceBind()
- @Operation(summary = "确认登录")
- @GetMapping("/confirmLogin/{ticket}")
- public ActionResult confirmLogin(@PathVariable("ticket") String ticket) throws LoginException {
- ScanCodeLoginConfigModel ticketModel = TicketUtil.parseTicket(ticket);
- if (ticketModel == null || !Objects.equals(ticketModel.getStatus(), 1)) {
- ticketModel = new ScanCodeLoginConfigModel();
- ticketModel.setStatus(ScanCodeTicketStatus.Invalid.getStatus());
- return ActionResult.success(ticketModel);
- }
- ticketModel.setStatus(ScanCodeTicketStatus.Success.getStatus());
- Map<String, String> parameters = new HashMap<>();
- parameters.put("grant_type", "scancode");
- parameters.put("token", UserProvider.getToken());
- ticketModel.setValue(authService.login(parameters).getData().getToken());
- TicketUtil.updateTicket(ticket, ticketModel, null);
- return ActionResult.success(ticketModel);
- }
- /**
- * 更改扫码凭证状态
- *
- * @param ticket
- * @return
- * @throws LoginException
- */
- @NoDataSourceBind()
- @Operation(summary = "更改扫码凭证状态")
- @GetMapping("/setCodeCertificateStatus/{ticket}/{status}")
- public ActionResult setCodeCertificateStatus(@PathVariable("ticket") String ticket, @PathVariable("status") Integer status) throws LoginException {
- ScanCodeLoginConfigModel ticketModel = TicketUtil.parseTicket(ticket);
- if (ticketModel == null) {
- ticketModel = new ScanCodeLoginConfigModel();
- ticketModel.setStatus(ScanCodeTicketStatus.Invalid.getStatus());
- } else {
- ticketModel.setStatus(status);
- }
- ticketModel.setTicketTimeout(System.currentTimeMillis() + configValueUtil.getCodeCertificateTimeout() * 1000);
- TicketUtil.updateTicket(ticket, ticketModel, configValueUtil.getCodeCertificateTimeout());
- return ActionResult.success(ticketModel);
- }
- /**
- * 获取用户登录信息
- *
- * @return
- * @throws LoginException 登录异常
- */
- @Operation(summary = "获取用户基本信息")
- @GetMapping("/me")
- public ActionResult<MeInfoVO> me() throws LoginException {
- UserInfo userInfo = UserProvider.getUser();
- MeInfoVO meInfoVO = new MeInfoVO()
- .setUserName(userInfo.getUserName())
- .setUserId(userInfo.getUserId())
- .setUserAccount(userInfo.getUserAccount())
- .setTenantId(userInfo.getTenantId());
- return ActionResult.success(meInfoVO);
- }
- @GetMapping("/white/jumpIndex")
- @NoDataSourceBind
- @Operation(summary = "跳转前端首页, 判断桌面端或者移动端跳转至不同的地址")
- public void jumpIndex(@RequestParam(value = "from", required = false) String from) throws IOException {
- String url = ServletUtil.getIsMobileDevice()?configValueUtil.getAppDomain():configValueUtil.getFrontDomain();
- UrlBuilder urlBuilder = UrlBuilder.of(url);
- if(StringUtil.isNotBlank(from)){
- urlBuilder.addQuery("from", from);
- }
- ServletUtil.getResponse().sendRedirect(urlBuilder.build());
- }
- }
|