Przeglądaj źródła

#238 飞书扫码登录失败

MaxKey 6 miesięcy temu
rodzic
commit
7efa9dd9f5

+ 1 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/jwt/AuthJwtService.java

@@ -119,7 +119,7 @@ public class AuthJwtService {
 	 * @return true or false
 	 */
 	public boolean validateJwtToken(String authToken) {
-		if(StringUtils.isNotBlank(authToken)) {
+		if(StringUtils.isNotBlank(authToken) && authToken.length() > 20) {
 			try {
 				JWTClaimsSet claims = resolve(authToken);
 				boolean isExpiration = claims.getExpirationTime().after(DateTime.now().toDate());

+ 1 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/interceptor/PermissionInterceptor.java

@@ -64,7 +64,7 @@ public class PermissionInterceptor  implements AsyncHandlerInterceptor  {
 		 SignPrincipal principal = AuthorizationUtils.getPrincipal();
 		//判断用户是否登录,判断用户是否登录用户
 		if(principal == null){
-			_logger.trace("No Authentication ... forward to /auth/entrypoint , request URI " + request.getRequestURI());
+			_logger.debug("No Authentication ... forward to /auth/entrypoint , request URI {}" , request.getRequestURI());
 			RequestDispatcher dispatcher = request.getRequestDispatcher("/auth/entrypoint");
 		    dispatcher.forward(request, response);
 		    return false;

+ 3 - 3
maxkey-starter/maxkey-starter-social/src/main/java/org/dromara/maxkey/authn/support/socialsignon/AbstractSocialSignOnEndpoint.java

@@ -107,11 +107,11 @@ public class AbstractSocialSignOnEndpoint {
         }
   		
   		AuthResponse<?> authResponse=authRequest.login(authCallback);
-  		_logger.debug("Response  : " + authResponse.getData());
+  		_logger.debug("Response  : {}" , authResponse.getData());
+  		String socialUserId = socialSignOnProviderService.getAccountId(provider, authResponse);
   		socialsAssociate =new SocialsAssociate();
 		socialsAssociate.setProvider(provider);
-		socialsAssociate.setSocialUserId(
-				socialSignOnProviderService.getAccountId(provider, authResponse));
+		socialsAssociate.setSocialUserId(socialUserId);
 		socialsAssociate.setInstId(instId);
 		
  		return socialsAssociate;

+ 65 - 79
maxkey-starter/maxkey-starter-social/src/main/java/org/dromara/maxkey/authn/support/socialsignon/SocialSignOnEndpoint.java

@@ -35,7 +35,6 @@ import org.dromara.maxkey.web.WebContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.Authentication;
-import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.*;
 
 import jakarta.servlet.http.HttpServletRequest;
@@ -47,17 +46,14 @@ import java.util.Map;
  * @author Crystal.Sea
  *
  */
-@Controller
+@RestController
 @RequestMapping(value = "/logon/oauth20")
 public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 	static final  Logger _logger = LoggerFactory.getLogger(SocialSignOnEndpoint.class);
 
-	@RequestMapping(value={"/authorize/{provider}"}, method = RequestMethod.GET)
-	@ResponseBody
-	public Message<Object> authorize( HttpServletRequest request,
-										@PathVariable("provider") String provider
-									) {
-		_logger.trace("SocialSignOn provider : " + provider);
+	@GetMapping("/authorize/{provider}")
+	public Message<Object> authorize( HttpServletRequest request,@PathVariable("provider") String provider) {
+		_logger.trace("SocialSignOn provider : {}" , provider);
 		String instId = WebContext.getInst().getId();
 		String originURL =WebContext.getContextPath(request,false);
     	String authorizationUrl =
@@ -67,14 +63,12 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 						originURL + applicationConfig.getFrontendUri()
 				).authorize(authTokenService.genRandomJwt());
 
-		_logger.trace("authorize SocialSignOn : " + authorizationUrl);
-		return new Message<Object>((Object)authorizationUrl);
+		_logger.trace("authorize SocialSignOn : {}" , authorizationUrl);
+		return new Message<Object>(authorizationUrl);
 	}
 
-	@RequestMapping(value={"/scanqrcode/{provider}"}, method = RequestMethod.GET)
-	@ResponseBody
-	public Message<SocialsProvider> scanQRCode(HttpServletRequest request,
-										@PathVariable("provider") String provider) {
+	@GetMapping("/scanqrcode/{provider}")
+	public Message<SocialsProvider> scanQRCode(HttpServletRequest request,@PathVariable("provider") String provider) {
 		String instId = WebContext.getInst().getId();
 		String originURL =WebContext.getContextPath(request,false);
 	    AuthRequest authRequest = 
@@ -82,30 +76,30 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 						instId,
 						provider,
 						originURL + applicationConfig.getFrontendUri());
-	   
-	    if(authRequest == null ) {
-	        _logger.error("build authRequest fail .");
+	    SocialsProvider scanQrProvider = null;
+	    if(authRequest != null ) {
+	        String state = UUID.generate().toString();
+		    //String state = authTokenService.genRandomJwt();
+		    authRequest.authorize(state);
+		    
+			SocialsProvider socialSignOnProvider = socialSignOnProviderService.get(instId,provider);
+			scanQrProvider = new SocialsProvider(socialSignOnProvider);
+			scanQrProvider.setState(state);
+			scanQrProvider.setRedirectUri(
+					socialSignOnProviderService.getRedirectUri(
+							originURL + applicationConfig.getFrontendUri(), provider));
+			//缓存state票据在缓存或者是redis中五分钟过期
+			if (provider.equalsIgnoreCase(AuthMaxkeyRequest.KEY)) {
+				socialSignOnProviderService.setToken(state);
+			}
+	    }else {
+	    	 _logger.error("build authRequest fail .");
 	    }
-		String state = UUID.generate().toString();
-	    //String state = authTokenService.genRandomJwt();
-	    authRequest.authorize(state);
-	    
-		SocialsProvider socialSignOnProvider = socialSignOnProviderService.get(instId,provider);
-		SocialsProvider scanQrProvider = new SocialsProvider(socialSignOnProvider);
-		scanQrProvider.setState(state);
-		scanQrProvider.setRedirectUri(
-				socialSignOnProviderService.getRedirectUri(
-						originURL + applicationConfig.getFrontendUri(), provider));
-		//缓存state票据在缓存或者是redis中五分钟过期
-		if (provider.equalsIgnoreCase(AuthMaxkeyRequest.KEY)) {
-			socialSignOnProviderService.setToken(state);
-		}
 		
-		return new Message<SocialsProvider>(scanQrProvider);
+		return new Message<>(scanQrProvider);
 	}
 
-	
-	@RequestMapping(value={"/bind/{provider}"}, method = RequestMethod.GET)
+	@GetMapping("/bind/{provider}")
 	public Message<AuthJwt> bind(@PathVariable("provider") String provider,
 								  @CurrentUser UserInfo userInfo,
 								  HttpServletRequest request) {
@@ -118,24 +112,18 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 		    socialsAssociate.setUserId(userInfo.getId());
 			socialsAssociate.setUsername(userInfo.getUsername());
 			socialsAssociate.setInstId(userInfo.getInstId());
-			//socialsAssociate.setAccessToken(JsonUtils.object2Json(accessToken));
-			//socialsAssociate.setExAttribute(JsonUtils.object2Json(accessToken.getResponseObject()));
-			_logger.debug("Social Bind : "+socialsAssociate);
+			_logger.debug("Social Bind : {}",socialsAssociate);
 			this.socialsAssociateService.delete(socialsAssociate);
 			this.socialsAssociateService.insert(socialsAssociate);
-			return new Message<AuthJwt>();
+			return new Message<>();
 	    }catch(Exception e) {
 	        _logger.error("callback Exception  ",e);
 	    }
-	    
-	    return new Message<AuthJwt>(Message.ERROR);
+	    return new Message<>(Message.ERROR);
 	}
 
-
-
-	@RequestMapping(value={"/callback/{provider}"}, method = RequestMethod.GET)
-	public Message<AuthJwt> callback(@PathVariable("provider") String provider,
-									  HttpServletRequest request) {
+	@GetMapping("/callback/{provider}")
+	public Message<AuthJwt> callback(@PathVariable("provider") String provider,HttpServletRequest request) {
 		 //auth call back may exception 
 	    try {
 	    	String originURL =WebContext.getContextPath(request,false);
@@ -145,36 +133,38 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 
 			SocialsAssociate socialssssociate1 = this.socialsAssociateService.get(socialsAssociate);
 		
-	    	_logger.debug("Loaded SocialSignOn Socials Associate : "+socialssssociate1);
+	    	_logger.debug("Loaded SocialSignOn Socials Associate : {}",socialssssociate1);
 		
 	    	if (null == socialssssociate1) {
 				//如果存在第三方ID并且在数据库无法找到映射关系,则进行绑定逻辑
 				if (StringUtils.isNotEmpty(socialsAssociate.getSocialUserId())) {
 					//返回message为第三方用户标识
-					return new Message<AuthJwt>(Message.PROMPT,socialsAssociate.getSocialUserId());
+					return new Message<>(Message.PROMPT,socialsAssociate.getSocialUserId());
 				}
 			}
 
 			socialsAssociate = socialssssociate1;
-	    	_logger.debug("Social Sign On from {} mapping to user {}",
+	    	if(socialsAssociate != null) {
+	    		_logger.debug("Social Sign On from {} mapping to user {}",
 		                socialsAssociate.getProvider(),socialsAssociate.getUsername());
-		
-	    	LoginCredential loginCredential =new LoginCredential(
-	    			socialsAssociate.getUsername(),"",ConstsLoginType.SOCIALSIGNON);
-	    	SocialsProvider socialSignOnProvider = socialSignOnProviderService.get(instId,provider);
-	    	loginCredential.setProvider(socialSignOnProvider.getProviderName());
-	    	
-	    	Authentication  authentication = authenticationProvider.authenticate(loginCredential,true);
-	    	//socialsAssociate.setAccessToken(JsonUtils.object2Json(this.accessToken));
-	    	socialsAssociate.setSocialUserInfo(accountJsonString);
-	    	//socialsAssociate.setExAttribute(JsonUtils.object2Json(accessToken.getResponseObject()));
-		
-	    	this.socialsAssociateService.update(socialsAssociate);
-	    	return new Message<AuthJwt>(authTokenService.genAuthJwt(authentication));
+		    	LoginCredential loginCredential =new LoginCredential(
+		    			socialsAssociate.getUsername(),"",ConstsLoginType.SOCIALSIGNON);
+		    	SocialsProvider socialSignOnProvider = socialSignOnProviderService.get(instId,provider);
+		    	loginCredential.setProvider(socialSignOnProvider.getProviderName());
+		    	
+		    	Authentication  authentication = authenticationProvider.authenticate(loginCredential,true);
+		    	socialsAssociate.setSocialUserInfo(accountJsonString);
+			
+		    	this.socialsAssociateService.update(socialsAssociate);
+		    	return new Message<>(authTokenService.genAuthJwt(authentication));
+	    	}else {
+	    		
+	    	}
 	    }catch(Exception e) {
 	    	 _logger.error("callback Exception  ",e);
-	    	 return new Message<AuthJwt>(Message.ERROR);
+	    	 
 	    }
+	    return new Message<>(Message.ERROR);
 	}
 
 
@@ -182,14 +172,14 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 	 * 提供给第三方应用关联用户接口
 	 * @return
 	 */
-	@RequestMapping(value={"/workweixin/qr/auth/login"}, method = {RequestMethod.POST})
+	@PostMapping("/workweixin/qr/auth/login")
 	public Message<AuthJwt> qrAuthLogin(
 			@RequestParam Map<String, String> param,
 			HttpServletRequest request) {
 
 		try {
 			if (null == param){
-				return new Message<AuthJwt>(Message.ERROR);
+				return new Message<>(Message.ERROR);
 			}
 			String token = param.get("token");
 			String username = param.get("username");
@@ -199,15 +189,15 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 				//设置token和用户绑定
 				boolean flag = this.socialSignOnProviderService.bindtoken(token,username);
 				if (flag) {
-					return new Message<AuthJwt>();
+					return new Message<>();
 				}
 			} else {
-				return new Message<AuthJwt>(Message.WARNING,"Invalid token");
+				return new Message<>(Message.WARNING,"Invalid token");
 			}
 		}catch(Exception e) {
 			_logger.error("qrAuthLogin Exception  ",e);
 		}
-		return new Message<AuthJwt>(Message.ERROR);
+		return new Message<>(Message.ERROR);
 	}
 
 
@@ -218,23 +208,23 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 	 * @param request
 	 * @return
 	 */
-	@RequestMapping(value={"/qrcallback/{provider}/{state}"}, method = RequestMethod.GET)
+	@PostMapping("/qrcallback/{provider}/{state}")
 	public Message<AuthJwt> qrcallback(@PathVariable("provider") String provider,@PathVariable("state") String state,
 										HttpServletRequest request) {
 		try {
 			//判断只有maxkey扫码
 			if (!provider.equalsIgnoreCase(AuthMaxkeyRequest.KEY)) {
-				return new Message<AuthJwt>(Message.ERROR);
+				return new Message<>(Message.ERROR);
 			}
 
 			String loginName = socialSignOnProviderService.getToken(state);
 			if (StringUtils.isEmpty(loginName)) {
 				//二维码过期
-				return new Message<AuthJwt>(Message.PROMPT);
+				return new Message<>(Message.PROMPT);
 			}
 			if("-1".equalsIgnoreCase(loginName)){
 				//暂无用户扫码
-				return new Message<AuthJwt>(Message.WARNING);
+				return new Message<>(Message.WARNING);
 			}
 			String instId = WebContext.getInst().getId();
 
@@ -246,29 +236,25 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 
 			socialsAssociate = this.socialsAssociateService.get(socialsAssociate);
 
-			_logger.debug("qrcallback Loaded SocialSignOn Socials Associate : "+socialsAssociate);
+			_logger.debug("qrcallback Loaded SocialSignOn Socials Associate : {}",socialsAssociate);
 
 			if(null == socialsAssociate) {
-				return new Message<AuthJwt>(Message.ERROR);
+				return new Message<>(Message.ERROR);
 			}
 
-			_logger.debug("qrcallback Social Sign On from {} mapping to user {}", socialsAssociate.getProvider(),socialsAssociate.getUsername());
-
 			LoginCredential loginCredential =new LoginCredential(
 					socialsAssociate.getUsername(),"",ConstsLoginType.SOCIALSIGNON);
 			SocialsProvider socialSignOnProvider = socialSignOnProviderService.get(instId,provider);
 			loginCredential.setProvider(socialSignOnProvider.getProviderName());
 
 			Authentication  authentication = authenticationProvider.authenticate(loginCredential,true);
-			//socialsAssociate.setAccessToken(JsonUtils.object2Json(this.accessToken));
 			socialsAssociate.setSocialUserInfo(accountJsonString);
-			//socialsAssociate.setExAttribute(JsonUtils.object2Json(accessToken.getResponseObject()));
 
 			this.socialsAssociateService.update(socialsAssociate);
-			return new Message<AuthJwt>(authTokenService.genAuthJwt(authentication));
+			return new Message<>(authTokenService.genAuthJwt(authentication));
 		}catch(Exception e) {
 			_logger.error("qrcallback Exception  ",e);
-			return new Message<AuthJwt>(Message.ERROR);
+			return new Message<>(Message.ERROR);
 		}
 	}
 }

+ 4 - 4
maxkey-starter/maxkey-starter-social/src/main/java/org/dromara/maxkey/authn/support/socialsignon/service/SocialSignOnProviderService.java

@@ -43,7 +43,7 @@ import me.zhyd.oauth.model.AuthUser;
 import me.zhyd.oauth.request.*;
 
 public class SocialSignOnProviderService{
-	private static Logger _logger = LoggerFactory.getLogger(SocialSignOnProviderService.class);
+	private static final Logger _logger = LoggerFactory.getLogger(SocialSignOnProviderService.class);
 	
 	private static final String DEFAULT_SELECT_STATEMENT = "select * from mxk_socials_provider where instid = ? and status = 1  order by sortindex";
 	
@@ -52,7 +52,7 @@ public class SocialSignOnProviderService{
                 .expireAfterWrite(ConstsTimeInterval.ONE_HOUR, TimeUnit.MINUTES)
                 .build();
 	
-	HashMap<String ,SocialsProvider>socialSignOnProviderMaps = new HashMap<String ,SocialsProvider>();
+	HashMap<String ,SocialsProvider>socialSignOnProviderMaps = new HashMap<>();
 	
 	private final JdbcTemplate jdbcTemplate;
 
@@ -199,9 +199,9 @@ public class SocialSignOnProviderService{
 		    List<SocialsProvider> listSocialsProvider = jdbcTemplate.query(
 		            DEFAULT_SELECT_STATEMENT,
 	                new SocialsProviderRowMapper(),instId);
-	        _logger.trace("query SocialsProvider " + listSocialsProvider);
+	        _logger.trace("query SocialsProvider {}" , listSocialsProvider);
 	        
-	        List<SocialsProvider> socialSignOnProviders = new ArrayList<SocialsProvider>();
+	        List<SocialsProvider> socialSignOnProviders = new ArrayList<>();
 	        socialsLogin = new SocialsProviderLogin(socialSignOnProviders);
 	        for(SocialsProvider socialsProvider : listSocialsProvider){
 	            _logger.debug("Social Provider {} ({})" ,

+ 2 - 2
maxkey-web-frontend/maxkey-web-app/src/app/core/net/default.interceptor.ts

@@ -107,14 +107,14 @@ export class DefaultInterceptor implements HttpInterceptor {
    */
   private refreshTokenRequest(): Observable<any> {
     const model = this.tokenSrv.get();
-    return this.http.post(`/auth/token/refresh`, null, { refresh_token: model?.['refresh_token'] || '' });
+    return this.http.post(`/auth/token/refresh?_allow_anonymous=true`, null, { refresh_token: model?.['refresh_token'] || '' });
   }
 
   // #region 刷新Token方式一:使用 401 重新刷新 Token
 
   private tryRefreshToken(ev: HttpResponseBase, req: HttpRequest<any>, next: HttpHandler): Observable<any> {
     // 1、若请求为刷新Token请求,表示来自刷新Token可以直接跳转登录页
-    if ([`/auth/token/refresh`].some(url => req.url.includes(url))) {
+    if ([`/auth/token/refresh?_allow_anonymous=true`].some(url => req.url.includes(url))) {
       this.toLogin();
       return throwError(ev);
     }

+ 5 - 8
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/callback.component.ts

@@ -19,9 +19,10 @@ import { ActivatedRoute, Router } from '@angular/router';
 import { ReuseTabService } from '@delon/abc/reuse-tab';
 import { SettingsService } from '@delon/theme';
 import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
+
 import { AuthnService } from '../../service/authn.service';
 import { SocialsProviderService } from '../../service/socials-provider.service';
-import {SocialsProviderBindUserComponent} from "./socials-provider-bind-user/socials-provider-bind-user.component";
+import { SocialsProviderBindUserComponent } from './socials-provider-bind-user/socials-provider-bind-user.component';
 
 @Component({
   selector: 'app-callback',
@@ -52,10 +53,9 @@ export class CallbackComponent implements OnInit {
           this.reuseTabService.clear();
           // 设置用户Token信息
           this.authnService.auth(res.data);
-        }
-        else if (res.code === 102) {
+        } else if (res.code === 102) {
           //绑定用户
-          this.openBindUser(res.message)
+          this.openBindUser(res.message);
           return;
         }
         this.authnService.navigate({});
@@ -70,7 +70,7 @@ export class CallbackComponent implements OnInit {
   }
 
   openBindUser(socialUserId: String) {
-    console.log("bind user : ",this.provider,socialUserId);
+    console.log('bind user : ', this.provider, socialUserId);
     const modal = this.modalService.create({
       nzContent: SocialsProviderBindUserComponent,
       nzViewContainerRef: this.viewContainerRef,
@@ -83,10 +83,7 @@ export class CallbackComponent implements OnInit {
     // Return a result when closed
     modal.afterClose.subscribe(result => {
       if (result.refresh) {
-
       }
     });
-
-
   }
 }

+ 5 - 5
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/login/login.component.html

@@ -14,7 +14,7 @@
       <i nz-icon nzType="mobile" nzTheme="outline"></i>
       {{ 'mxk.login.tab-mobile' | i18n }}
     </label>
-    <label nz-radio-button nzValue="qrscan" style="width: 50%; text-align: center" (click)="getLoginQrCode()">
+    <label nz-radio-button nzValue="qrscan" style="width: 50%; text-align: center" (click)="getScanQrCode()">
       <i nz-icon nzType="qrcode" nzTheme="outline"></i>{{ 'mxk.login.tab-qrscan' | i18n }}
     </label>
   </nz-radio-group>
@@ -82,10 +82,10 @@
       </nz-form-control>
     </nz-form-item>
   </div>
-  <div nz-row *ngIf="loginType=='qrscan'">
-    <div class="qrcode" id="div_qrcodelogin" style="background: #fff;padding: 20px;"></div>
-    <div id="qrexpire" *ngIf="qrexpire" style="width: 100%;text-align: center;background: #fff;padding-bottom: 20px;">
-      二维码过期 <a href="javascript:void(0);" (click)="getLoginQrCode()">刷新</a>
+  <div nz-row *ngIf="loginType == 'qrscan'">
+    <div class="qrcode" id="div_qrcodelogin" style="background: #fff; padding: 20px"></div>
+    <div id="qrexpire" *ngIf="qrexpire" style="width: 100%; text-align: center; background: #fff; padding-bottom: 20px">
+      二维码过期 <a href="javascript:void(0);" (click)="getScanQrCode()">刷新</a>
     </div>
   </div>
   <nz-form-item *ngIf="loginType == 'normal' || loginType == 'mobile'">

+ 36 - 39
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/login/login.component.ts

@@ -45,9 +45,9 @@ export class UserLoginComponent implements OnInit, OnDestroy {
     providers: NzSafeAny[];
     qrScan: string;
   } = {
-      providers: [],
-      qrScan: ''
-    };
+    providers: [],
+    qrScan: ''
+  };
 
   form: FormGroup;
   error = '';
@@ -309,32 +309,50 @@ export class UserLoginComponent implements OnInit, OnDestroy {
   /**
    * 获取二维码
    */
-  getLoginQrCode() {
-    this.qrexpire = false;
-
-    this.qrCodeService.getLoginQrCode().subscribe(res => {
-      if (res.code === 0 && res.data.rqCode) {
-        // 使用返回的 rqCode
-        const qrImageElement = document.getElementById('div_qrcodelogin');
-        this.ticket = res.data.ticket;
-        if (qrImageElement) {
-          qrImageElement.innerHTML = `<img src="${res.data.rqCode}" alt="QR Code" style="width: 200px; height: 200px;">`;
+  getScanQrCode() {
+    this.authnService.clearUser();
+    console.log(`qrScan : ${this.socials.qrScan}`);
+    if (this.socials.qrScan === 'workweixin' || this.socials.qrScan === 'dingtalk' || this.socials.qrScan === 'feishu') {
+      this.socialsProviderService.scanqrcode(this.socials.qrScan).subscribe(res => {
+        if (res.code === 0) {
+          if (this.socials.qrScan === 'workweixin') {
+            this.qrScanWorkweixin(res.data);
+          } else if (this.socials.qrScan === 'dingtalk') {
+            this.qrScanDingtalk(res.data);
+          } else if (this.socials.qrScan === 'feishu') {
+            this.qrScanFeishu(res.data);
+          }
         }
+      });
+    } else {
+      this.qrexpire = false;
+      if (this.interval$) {
+        clearInterval(this.interval$);
+      }
+      this.qrCodeService.getLoginQrCode().subscribe(res => {
+        if (res.code === 0 && res.data.rqCode) {
+          // 使用返回的 rqCode
+          const qrImageElement = document.getElementById('div_qrcodelogin');
+          this.ticket = res.data.ticket;
+          if (qrImageElement) {
+            qrImageElement.innerHTML = `<img src="${res.data.rqCode}" alt="QR Code" style="width: 200px; height: 200px;">`;
+          }
 
-        /*   // 设置5分钟后 qrexpire 为 false
+          /*   // 设置5分钟后 qrexpire 为 false
         setTimeout(() => {
           this.qrexpire = true;
           this.cdr.detectChanges(); // 更新视图
         }, 5 * 60 * 1000); // 5 分钟*/
-        this.loginByQrCode();
-      }
-    });
+          this.scanQrCodeLogin();
+        }
+      });
+    }
   }
 
   /**
    * 二维码轮询登录
    */
-  loginByQrCode() {
+  scanQrCodeLogin() {
     const interval = setInterval(() => {
       this.qrCodeService
         .loginByQrCode({
@@ -369,27 +387,6 @@ export class UserLoginComponent implements OnInit, OnDestroy {
     }, 5 * 1000); // 5 seconds
   }
 
-  getQrCode(): void {
-    this.qrexpire = false;
-    if (this.interval$) {
-      clearInterval(this.interval$);
-    }
-    this.authnService.clearUser();
-    this.socialsProviderService.scanqrcode(this.socials.qrScan).subscribe(res => {
-      if (res.code === 0) {
-        if (this.socials.qrScan === 'workweixin') {
-          this.qrScanWorkweixin(res.data);
-        } else if (this.socials.qrScan === 'dingtalk') {
-          this.qrScanDingtalk(res.data);
-        } else if (this.socials.qrScan === 'maxkey') {
-          this.qrScanMaxkey(res.data);
-        } else if (this.socials.qrScan === 'feishu') {
-          this.qrScanFeishu(res.data);
-        }
-      }
-    });
-  }
-
   // #endregion
 
   ngOnDestroy(): void {

+ 1 - 1
maxkey-web-frontend/maxkey-web-app/src/app/service/socials-provider.service.ts

@@ -51,7 +51,7 @@ export class SocialsProviderService extends BaseService<SocialsProvider> {
     return this.getByParams(params, `/logon/oauth20/bind/${provider}?_allow_anonymous=true`);
   }
 
-  qrcallback(provider: string, token: string ): Observable<Message<SocialsProvider>> {
+  qrcallback(provider: string, token: string): Observable<Message<SocialsProvider>> {
     return this.getByParams({}, `/logon/oauth20/qrcallback/${provider}/${token}?_allow_anonymous=true`);
   }
 }

+ 3 - 3
maxkey-web-frontend/maxkey-web-app/src/index.html

@@ -168,8 +168,9 @@
 </script>
 
 <!--飞书-->
-<!--
-<script src="http://sf3-cn.feishucdn.com/obj/static/lark/passport/qrcode/LarkSSOSDKWebQRCode-1.0.1.js"></script>
+
+<script src="http://lf-package-cn.feishucdn.com/obj/feishu-static/lark/passport/qrcode/LarkSSOSDKWebQRCode-1.0.3.js"></script>
+
 <script type="text/javascript">
   var fsredirectUri = "";
   var QRLoginObj;
@@ -190,6 +191,5 @@
     window.attachEvent('onmessage', handleMessage);
   }
 </script>
--->
 
 </html>

+ 1 - 0
maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/autoconfigure/MaxKeyMvcConfig.java

@@ -107,6 +107,7 @@ public class MaxKeyMvcConfig implements WebMvcConfigurer {
         		.addPathPatterns("/logout")
                 .addPathPatterns("/logout/**")
                 .addPathPatterns("/authz/refused")
+                .excludePathPatterns("/logon/oauth20/**/**")
                 .excludePathPatterns("/swagger-ui/**")
                 .excludePathPatterns("/swagger-resources/**")
                 .excludePathPatterns("/v3/api-docs/**")