提交 0f912df2 编写于 作者: M MaxKey

CONGRESS

上级 eb748ac8
...@@ -25,14 +25,30 @@ import org.maxkey.authn.SignPrincipal; ...@@ -25,14 +25,30 @@ import org.maxkey.authn.SignPrincipal;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import com.fasterxml.jackson.annotation.JsonProperty;
public class AuthJwt implements Serializable { public class AuthJwt implements Serializable {
private static final long serialVersionUID = -914373258878811144L; private static final long serialVersionUID = -914373258878811144L;
public static final String ACCESS_TOKEN = "access_token";
public static final String REFRESH_TOKEN = "refresh_token";
public static final String EXPIRES_IN = "expired";
private String ticket; private String ticket;
private String type = "Bearer";
private String token; private String token;
@JsonProperty(REFRESH_TOKEN)
private String refreshToken; private String refreshToken;
private String type = "Bearer";
@JsonProperty(EXPIRES_IN)
private int expiresIn;
private String remeberMe; private String remeberMe;
private String id; private String id;
private String name; private String name;
...@@ -44,27 +60,36 @@ public class AuthJwt implements Serializable { ...@@ -44,27 +60,36 @@ public class AuthJwt implements Serializable {
private int passwordSetType; private int passwordSetType;
private List<String> authorities; private List<String> authorities;
public AuthJwt(String ticket, String type, String token, String refreshToken, int expiresIn, String remeberMe,
public AuthJwt(String token, String id, String username, String displayName, String email, String instId, String id, String name, String username, String displayName, String email, String instId, String instName,
String instName, List<String> authorities) { int passwordSetType, List<String> authorities) {
super();
this.ticket = ticket;
this.type = type;
this.token = token; this.token = token;
this.refreshToken = refreshToken;
this.expiresIn = expiresIn;
this.remeberMe = remeberMe;
this.id = id; this.id = id;
this.name = username; this.name = name;
this.username = username; this.username = username;
this.displayName = displayName; this.displayName = displayName;
this.email = email; this.email = email;
this.instId = instId; this.instId = instId;
this.instName = instName; this.instName = instName;
this.passwordSetType = passwordSetType;
this.authorities = authorities; this.authorities = authorities;
} }
public AuthJwt(String token,String refreshToken, Authentication authentication) {
public AuthJwt(String token, Authentication authentication,int expiresIn,String refreshToken) {
SignPrincipal principal = ((SignPrincipal)authentication.getPrincipal()); SignPrincipal principal = ((SignPrincipal)authentication.getPrincipal());
this.token = token; this.token = token;
this.expiresIn = expiresIn;
this.refreshToken = refreshToken; this.refreshToken = refreshToken;
this.ticket = principal.getSession().getId();
this.ticket = principal.getSession().getId();
this.id = principal.getUserInfo().getId(); this.id = principal.getUserInfo().getId();
this.username = principal.getUserInfo().getUsername(); this.username = principal.getUserInfo().getUsername();
this.name = this.username; this.name = this.username;
...@@ -175,6 +200,16 @@ public class AuthJwt implements Serializable { ...@@ -175,6 +200,16 @@ public class AuthJwt implements Serializable {
public void setRefreshToken(String refreshToken) { public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken; this.refreshToken = refreshToken;
} }
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
@Override @Override
public String toString() { public String toString() {
......
...@@ -7,6 +7,7 @@ import org.joda.time.DateTime; ...@@ -7,6 +7,7 @@ import org.joda.time.DateTime;
import org.maxkey.authn.SignPrincipal; import org.maxkey.authn.SignPrincipal;
import org.maxkey.crypto.jwt.HMAC512Service; import org.maxkey.crypto.jwt.HMAC512Service;
import org.maxkey.entity.UserInfo; import org.maxkey.entity.UserInfo;
import org.maxkey.util.StringUtils;
import org.maxkey.web.WebContext; import org.maxkey.web.WebContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -33,7 +34,7 @@ public class AuthJwtService { ...@@ -33,7 +34,7 @@ public class AuthJwtService {
DateTime currentDateTime = DateTime.now(); DateTime currentDateTime = DateTime.now();
String subject = principal.getUsername(); String subject = principal.getUsername();
Date expirationTime = currentDateTime.plusSeconds(expires).toDate(); Date expirationTime = currentDateTime.plusSeconds(expires).toDate();
_logger.debug("jwt subject : {} , expiration Time : {}" , subject,expirationTime); _logger.trace("jwt subject : {} , expiration Time : {}" , subject,expirationTime);
JWTClaimsSet jwtClaims =new JWTClaimsSet.Builder() JWTClaimsSet jwtClaims =new JWTClaimsSet.Builder()
.issuer(issuer) .issuer(issuer)
...@@ -102,12 +103,14 @@ public class AuthJwtService { ...@@ -102,12 +103,14 @@ public class AuthJwtService {
*/ */
public boolean validateJwtToken(String authToken) { public boolean validateJwtToken(String authToken) {
try { try {
JWTClaimsSet claims = resolve(authToken); if(StringUtils.isNotBlank(authToken)) {
boolean isExpiration = claims.getExpirationTime().after(DateTime.now().toDate()); JWTClaimsSet claims = resolve(authToken);
boolean isVerify = hmac512Service.verify(authToken); boolean isExpiration = claims.getExpirationTime().after(DateTime.now().toDate());
_logger.debug("JWT Verify {} , now {} , ExpirationTime {} , isExpiration : {}" , boolean isVerify = hmac512Service.verify(authToken);
isVerify,DateTime.now().toDate(),claims.getExpirationTime(),isExpiration); _logger.trace("JWT Verify {} , now {} , ExpirationTime {} , isExpiration : {}" ,
return isVerify && isExpiration; isVerify,DateTime.now().toDate(),claims.getExpirationTime(),isExpiration);
return isVerify && isExpiration;
}
} catch (ParseException e) { } catch (ParseException e) {
_logger.error("authToken {}",authToken); _logger.error("authToken {}",authToken);
_logger.error("ParseException ",e); _logger.error("ParseException ",e);
......
...@@ -66,13 +66,22 @@ public class AuthTokenService extends AuthJwtService{ ...@@ -66,13 +66,22 @@ public class AuthTokenService extends AuthJwtService{
public AuthJwt genAuthJwt(Authentication authentication) { public AuthJwt genAuthJwt(Authentication authentication) {
if(authentication != null) { if(authentication != null) {
String refreshToken = refreshTokenService.genRefreshToken(authentication); String refreshToken = refreshTokenService.genRefreshToken(authentication);
return new AuthJwt(genJwt(authentication),refreshToken, authentication); String accessToken = genJwt(authentication);
AuthJwt authJwt = new AuthJwt(
accessToken,
authentication,
authJwkConfig.getExpires(),
refreshToken);
return authJwt;
} }
return null; return null;
} }
public String genJwt(Authentication authentication) { public String genJwt(Authentication authentication) {
return genJwt( authentication,authJwkConfig.getIssuer(),authJwkConfig.getExpires()); return genJwt(
authentication,
authJwkConfig.getIssuer(),
authJwkConfig.getExpires());
} }
...@@ -100,8 +109,9 @@ public class AuthTokenService extends AuthJwtService{ ...@@ -100,8 +109,9 @@ public class AuthTokenService extends AuthJwtService{
congress, congress,
new AuthJwt( new AuthJwt(
genJwt(authentication), genJwt(authentication),
refreshToken, authentication,
authentication) authJwkConfig.getExpires(),
refreshToken)
); );
return congress; return congress;
} }
......
...@@ -37,18 +37,23 @@ import org.springframework.security.core.Authentication; ...@@ -37,18 +37,23 @@ import org.springframework.security.core.Authentication;
public class AuthorizationUtils { public class AuthorizationUtils {
private static final Logger _logger = LoggerFactory.getLogger(AuthorizationUtils.class); private static final Logger _logger = LoggerFactory.getLogger(AuthorizationUtils.class);
public static final String Authorization_Cookie = "congress"; public static final class BEARERTYPE{
public static final String CONGRESS = "congress";
public static final String AUTHORIZATION = "Authorization";
}
public static void authenticateWithCookie( public static void authenticateWithCookie(
HttpServletRequest request, HttpServletRequest request,
AuthTokenService authTokenService, AuthTokenService authTokenService,
SessionManager sessionManager SessionManager sessionManager
) throws ParseException{ ) throws ParseException{
Cookie authCookie = WebContext.getCookie(request, Authorization_Cookie); Cookie authCookie = WebContext.getCookie(request, BEARERTYPE.CONGRESS);
if(authCookie != null ) { if(authCookie != null ) {
String authorization = authCookie.getValue(); String authorization = authCookie.getValue();
doJwtAuthenticate(authorization,authTokenService,sessionManager); _logger.trace("Try congress authenticate .");
_logger.debug("congress automatic authenticated ."); doJwtAuthenticate(BEARERTYPE.CONGRESS,authorization,authTokenService,sessionManager);
} }
} }
...@@ -59,13 +64,14 @@ public class AuthorizationUtils { ...@@ -59,13 +64,14 @@ public class AuthorizationUtils {
) throws ParseException{ ) throws ParseException{
String authorization = AuthorizationHeaderUtils.resolveBearer(request); String authorization = AuthorizationHeaderUtils.resolveBearer(request);
if(authorization != null ) { if(authorization != null ) {
doJwtAuthenticate(authorization,authTokenService,sessionManager); _logger.trace("Try Authorization authenticate .");
_logger.debug("Authorization automatic authenticated ."); doJwtAuthenticate(BEARERTYPE.AUTHORIZATION,authorization,authTokenService,sessionManager);
} }
} }
public static void doJwtAuthenticate( public static void doJwtAuthenticate(
String bearerType,
String authorization, String authorization,
AuthTokenService authTokenService, AuthTokenService authTokenService,
SessionManager sessionManager) throws ParseException { SessionManager sessionManager) throws ParseException {
...@@ -75,12 +81,17 @@ public class AuthorizationUtils { ...@@ -75,12 +81,17 @@ public class AuthorizationUtils {
Session session = sessionManager.get(sessionId); Session session = sessionManager.get(sessionId);
if(session != null) { if(session != null) {
setAuthentication(session.getAuthentication()); setAuthentication(session.getAuthentication());
_logger.debug("{} Automatic authenticated .",bearerType);
}else { }else {
setAuthentication(null); //time out
_logger.debug("Session timeout .");
clearAuthentication();
} }
} }
}else { }else {
setAuthentication(null); //token invalidate
_logger.debug("Token invalidate .");
clearAuthentication();
} }
} }
...@@ -100,6 +111,10 @@ public class AuthorizationUtils { ...@@ -100,6 +111,10 @@ public class AuthorizationUtils {
WebContext.setAttribute(WebConstants.AUTHENTICATION, authentication); WebContext.setAttribute(WebConstants.AUTHENTICATION, authentication);
} }
public static void clearAuthentication() {
WebContext.removeAttribute(WebConstants.AUTHENTICATION);
}
public static boolean isAuthenticated() { public static boolean isAuthenticated() {
return getAuthentication() != null; return getAuthentication() != null;
} }
......
...@@ -33,6 +33,7 @@ public class LoginRefreshPoint { ...@@ -33,6 +33,7 @@ public class LoginRefreshPoint {
@RequestMapping(value={"/token/refresh"}, produces = {MediaType.APPLICATION_JSON_VALUE}) @RequestMapping(value={"/token/refresh"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> refresh( public ResponseEntity<?> refresh(
@RequestHeader(name = "refresh_token", required = true) String refreshToken) { @RequestHeader(name = "refresh_token", required = true) String refreshToken) {
_logger.debug("try to refresh token " );
_logger.trace("refresh token {} " , refreshToken); _logger.trace("refresh token {} " , refreshToken);
try { try {
if(refreshTokenService.validateJwtToken(refreshToken)) { if(refreshTokenService.validateJwtToken(refreshToken)) {
...@@ -47,7 +48,7 @@ public class LoginRefreshPoint { ...@@ -47,7 +48,7 @@ public class LoginRefreshPoint {
_logger.debug("Session is timeout , sessionId [{}]" , sessionId); _logger.debug("Session is timeout , sessionId [{}]" , sessionId);
} }
}else { }else {
_logger.trace("refresh token is not validate ."); _logger.debug("refresh token is not validate .");
} }
}catch(Exception e) { }catch(Exception e) {
_logger.error("Refresh Exception !",e); _logger.error("Refresh Exception !",e);
......
...@@ -22,6 +22,7 @@ import java.util.LinkedHashMap; ...@@ -22,6 +22,7 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import org.maxkey.authn.annotation.CurrentUser; import org.maxkey.authn.annotation.CurrentUser;
import org.maxkey.authn.jwt.AuthTokenService;
import org.maxkey.authn.web.AuthorizationUtils; import org.maxkey.authn.web.AuthorizationUtils;
import org.maxkey.authz.oauth2.common.OAuth2Constants; import org.maxkey.authz.oauth2.common.OAuth2Constants;
import org.maxkey.authz.oauth2.provider.AuthorizationRequest; import org.maxkey.authz.oauth2.provider.AuthorizationRequest;
...@@ -81,6 +82,9 @@ public class OAuth20AccessConfirmationEndpoint { ...@@ -81,6 +82,9 @@ public class OAuth20AccessConfirmationEndpoint {
@Autowired @Autowired
protected ApplicationConfig applicationConfig; protected ApplicationConfig applicationConfig;
@Autowired
AuthTokenService authTokenService;
/** /**
* getAccessConfirmation. * getAccessConfirmation.
* @param model Map * @param model Map
...@@ -95,7 +99,7 @@ public class OAuth20AccessConfirmationEndpoint { ...@@ -95,7 +99,7 @@ public class OAuth20AccessConfirmationEndpoint {
AuthorizationRequest clientAuth = AuthorizationRequest clientAuth =
(AuthorizationRequest) momentaryService.get(currentUser.getSessionId(), "authorizationRequest"); (AuthorizationRequest) momentaryService.get(currentUser.getSessionId(), "authorizationRequest");
ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId(),true); ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId(),true);
model.put("oauth_approval", WebContext.genId()); model.put("oauth_approval", authTokenService.genRandomJwt());
model.put("auth_request", clientAuth); model.put("auth_request", clientAuth);
model.put("client", client); model.put("client", client);
model.put("oauth_version", "oauth 2.0"); model.put("oauth_version", "oauth 2.0");
...@@ -136,7 +140,7 @@ public class OAuth20AccessConfirmationEndpoint { ...@@ -136,7 +140,7 @@ public class OAuth20AccessConfirmationEndpoint {
@PathVariable("oauth_approval") String oauth_approval, @PathVariable("oauth_approval") String oauth_approval,
@CurrentUser UserInfo currentUser) { @CurrentUser UserInfo currentUser) {
Map<String, Object> model = new HashMap<String, Object>(); Map<String, Object> model = new HashMap<String, Object>();
if(StringUtils.isNotBlank(oauth_approval)) { if(authTokenService.validateJwtToken(oauth_approval)) {
try { try {
AuthorizationRequest clientAuth = AuthorizationRequest clientAuth =
(AuthorizationRequest) momentaryService.get(currentUser.getSessionId(), "authorizationRequest"); (AuthorizationRequest) momentaryService.get(currentUser.getSessionId(), "authorizationRequest");
......
...@@ -45,6 +45,7 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -45,6 +45,7 @@ export class DefaultInterceptor implements HttpInterceptor {
private refreshTokenEnabled = environment.api.refreshTokenEnabled; private refreshTokenEnabled = environment.api.refreshTokenEnabled;
private refreshTokenType: 're-request' | 'auth-refresh' = environment.api.refreshTokenType; private refreshTokenType: 're-request' | 'auth-refresh' = environment.api.refreshTokenType;
private refreshToking = false; private refreshToking = false;
private notified = false;
private refreshToken$: BehaviorSubject<any> = new BehaviorSubject<any>(null); private refreshToken$: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private injector: Injector) { constructor(private injector: Injector) {
...@@ -70,7 +71,10 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -70,7 +71,10 @@ export class DefaultInterceptor implements HttpInterceptor {
} }
private goTo(url: string): void { private goTo(url: string): void {
setTimeout(() => this.injector.get(Router).navigateByUrl(url)); setTimeout(() => {
this.injector.get(Router).navigateByUrl(url);
this.notified = false;
});
} }
private checkStatus(ev: HttpResponseBase): void { private checkStatus(ev: HttpResponseBase): void {
...@@ -87,7 +91,7 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -87,7 +91,7 @@ export class DefaultInterceptor implements HttpInterceptor {
*/ */
private refreshTokenRequest(): Observable<any> { private refreshTokenRequest(): Observable<any> {
const model = this.tokenSrv.get(); const model = this.tokenSrv.get();
return this.http.post(`/auth/token/refresh`, null, null, { headers: { refresh_token: model?.['refreshToken'] || '' } }); return this.http.post(`/auth/token/refresh`, null, null, { headers: { refresh_token: model?.['refresh_token'] || '' } });
} }
// #region 刷新Token方式一:使用 401 重新刷新 Token // #region 刷新Token方式一:使用 401 重新刷新 Token
...@@ -117,7 +121,7 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -117,7 +121,7 @@ export class DefaultInterceptor implements HttpInterceptor {
console.log(res.data); console.log(res.data);
// 通知后续请求继续执行 // 通知后续请求继续执行
this.refreshToking = false; this.refreshToking = false;
this.refreshToken$.next(res.data.refreshToken); this.refreshToken$.next(res.data.refresh_token);
this.cookieService.set(CONSTS.CONGRESS, res.data.token); this.cookieService.set(CONSTS.CONGRESS, res.data.token);
// 重新保存新 token // 重新保存新 token
this.tokenSrv.set(res.data); this.tokenSrv.set(res.data);
...@@ -181,8 +185,11 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -181,8 +185,11 @@ export class DefaultInterceptor implements HttpInterceptor {
// #endregion // #endregion
private toLogin(): void { private toLogin(): void {
this.notification.error(`未登录或登录已过期,请重新登录。`, ``); if (!this.notified) {
this.goTo(this.tokenSrv.login_url!); this.notified = true;
this.notification.error(`未登录或登录已过期,请重新登录。`, ``);
this.goTo(this.tokenSrv.login_url!);
}
} }
private handleData(ev: HttpResponseBase, req: HttpRequest<any>, next: HttpHandler): Observable<any> { private handleData(ev: HttpResponseBase, req: HttpRequest<any>, next: HttpHandler): Observable<any> {
...@@ -227,10 +234,7 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -227,10 +234,7 @@ export class DefaultInterceptor implements HttpInterceptor {
break; break;
default: default:
if (ev instanceof HttpErrorResponse) { if (ev instanceof HttpErrorResponse) {
console.warn( console.warn('未可知错误,大部分是由于后端不支持跨域CORS或无效配置引起.', ev);
'未可知错误,大部分是由于后端不支持跨域CORS或无效配置引起,请参考 https://ng-alain.com/docs/server 解决跨域问题',
ev
);
} }
break; break;
} }
......
...@@ -78,7 +78,14 @@ import { LayoutDefaultOptions } from '../../theme/layout-default'; ...@@ -78,7 +78,14 @@ import { LayoutDefaultOptions } from '../../theme/layout-default';
<router-outlet></router-outlet> <router-outlet></router-outlet>
</ng-template> </ng-template>
</layout-default> </layout-default>
<global-footer style="border-top: 1px solid #e5e5e5; min-height: 120px; text-shadow: 0 1px 0 #fff;margin:0;">
<div style="margin-top: 30px">
MaxKey v3.5.0 GA<br />
Copyright
<i nz-icon nzType="copyright"></i> 2022 <a href="//www.maxkey.top" target="_blank">http://www.maxkey.top</a><br />
Licensed under the Apache License, Version 2.0
</div>
</global-footer>
<setting-drawer *ngIf="showSettingDrawer"></setting-drawer> <setting-drawer *ngIf="showSettingDrawer"></setting-drawer>
<theme-btn></theme-btn> <theme-btn></theme-btn>
` `
......
...@@ -73,7 +73,7 @@ export class AuthenticationService { ...@@ -73,7 +73,7 @@ export class AuthenticationService {
} }
this.cookieService.set(CONSTS.CONGRESS, authJwt.token); this.cookieService.set(CONSTS.CONGRESS, authJwt.token);
this.cookieService.set(CONSTS.CONGRESS, authJwt.ticket, { domain: subHostName }); this.cookieService.set(CONSTS.ONLINE_TICKET, authJwt.ticket, { domain: subHostName });
if (authJwt.remeberMe) { if (authJwt.remeberMe) {
localStorage.setItem(CONSTS.REMEMBER, authJwt.remeberMe); localStorage.setItem(CONSTS.REMEMBER, authJwt.remeberMe);
} }
......
export const CONSTS = { export const CONSTS = {
CONGRESS: 'congress', CONGRESS: 'congress',
ONLINE_TICKET: 'online_ticket',
REDIRECT_URI: 'redirect_uri', REDIRECT_URI: 'redirect_uri',
REMEMBER: 'remember_me' REMEMBER: 'remember_me'
}; };
...@@ -13,9 +13,12 @@ import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth'; ...@@ -13,9 +13,12 @@ import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
import { ALAIN_I18N_TOKEN, _HttpClient } from '@delon/theme'; import { ALAIN_I18N_TOKEN, _HttpClient } from '@delon/theme';
import { environment } from '@env/environment'; import { environment } from '@env/environment';
import { NzNotificationService } from 'ng-zorro-antd/notification'; import { NzNotificationService } from 'ng-zorro-antd/notification';
import { CookieService } from 'ngx-cookie-service';
import { BehaviorSubject, Observable, of, throwError } from 'rxjs'; import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
import { catchError, filter, mergeMap, switchMap, take } from 'rxjs/operators'; import { catchError, filter, mergeMap, switchMap, take } from 'rxjs/operators';
import { CONSTS } from '../../shared/consts';
const CODEMESSAGE: { [key: number]: string } = { const CODEMESSAGE: { [key: number]: string } = {
200: '服务器成功返回请求的数据。', 200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。', 201: '新建或修改数据成功。',
...@@ -42,6 +45,7 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -42,6 +45,7 @@ export class DefaultInterceptor implements HttpInterceptor {
private refreshTokenEnabled = environment.api.refreshTokenEnabled; private refreshTokenEnabled = environment.api.refreshTokenEnabled;
private refreshTokenType: 're-request' | 'auth-refresh' = environment.api.refreshTokenType; private refreshTokenType: 're-request' | 'auth-refresh' = environment.api.refreshTokenType;
private refreshToking = false; private refreshToking = false;
private notified = false;
private refreshToken$: BehaviorSubject<any> = new BehaviorSubject<any>(null); private refreshToken$: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private injector: Injector) { constructor(private injector: Injector) {
...@@ -54,6 +58,10 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -54,6 +58,10 @@ export class DefaultInterceptor implements HttpInterceptor {
return this.injector.get(NzNotificationService); return this.injector.get(NzNotificationService);
} }
private get cookieService(): CookieService {
return this.injector.get(CookieService);
}
private get tokenSrv(): ITokenService { private get tokenSrv(): ITokenService {
return this.injector.get(DA_SERVICE_TOKEN); return this.injector.get(DA_SERVICE_TOKEN);
} }
...@@ -63,7 +71,10 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -63,7 +71,10 @@ export class DefaultInterceptor implements HttpInterceptor {
} }
private goTo(url: string): void { private goTo(url: string): void {
setTimeout(() => this.injector.get(Router).navigateByUrl(url)); setTimeout(() => {
this.injector.get(Router).navigateByUrl(url);
this.notified = false;
});
} }
private checkStatus(ev: HttpResponseBase): void { private checkStatus(ev: HttpResponseBase): void {
...@@ -91,6 +102,7 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -91,6 +102,7 @@ export class DefaultInterceptor implements HttpInterceptor {
this.toLogin(); this.toLogin();
return throwError(ev); return throwError(ev);
} }
// 2、如果 `refreshToking` 为 `true` 表示已经在请求刷新 Token 中,后续所有请求转入等待状态,直至结果返回后再重新发起请求 // 2、如果 `refreshToking` 为 `true` 表示已经在请求刷新 Token 中,后续所有请求转入等待状态,直至结果返回后再重新发起请求
if (this.refreshToking) { if (this.refreshToking) {
return this.refreshToken$.pipe( return this.refreshToken$.pipe(
...@@ -99,17 +111,20 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -99,17 +111,20 @@ export class DefaultInterceptor implements HttpInterceptor {
switchMap(() => next.handle(this.reAttachToken(req))) switchMap(() => next.handle(this.reAttachToken(req)))
); );
} }
// 3、尝试调用刷新 Token // 3、尝试调用刷新 Token
this.refreshToking = true; this.refreshToking = true;
this.refreshToken$.next(null); this.refreshToken$.next(null);
return this.refreshTokenRequest().pipe( return this.refreshTokenRequest().pipe(
switchMap(res => { switchMap(res => {
console.log(res.data);
// 通知后续请求继续执行 // 通知后续请求继续执行
this.refreshToking = false; this.refreshToking = false;
this.refreshToken$.next(res); this.refreshToken$.next(res.data.refresh_token);
this.cookieService.set(CONSTS.CONGRESS, res.data.token);
// 重新保存新 token // 重新保存新 token
this.tokenSrv.set(res); this.tokenSrv.set(res.data);
// 重新发起请求 // 重新发起请求
return next.handle(this.reAttachToken(req)); return next.handle(this.reAttachToken(req));
}), }),
...@@ -127,11 +142,14 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -127,11 +142,14 @@ export class DefaultInterceptor implements HttpInterceptor {
* > 由于已经发起的请求,不会再走一遍 `@delon/auth` 因此需要结合业务情况重新附加新的 Token * > 由于已经发起的请求,不会再走一遍 `@delon/auth` 因此需要结合业务情况重新附加新的 Token
*/ */
private reAttachToken(req: HttpRequest<any>): HttpRequest<any> { private reAttachToken(req: HttpRequest<any>): HttpRequest<any> {
//console.log('reAttachToken');
// 以下示例是以 NG-ALAIN 默认使用 `SimpleInterceptor` // 以下示例是以 NG-ALAIN 默认使用 `SimpleInterceptor`
const token = this.tokenSrv.get()?.token; const token = this.tokenSrv.get()?.token;
return req.clone({ return req.clone({
setHeaders: { setHeaders: {
Authorization: `Bearer ${token}` Authorization: `Bearer ${token}`,
hostname: window.location.hostname,
AuthServer: 'MaxKey'
} }
}); });
} }
...@@ -167,8 +185,11 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -167,8 +185,11 @@ export class DefaultInterceptor implements HttpInterceptor {
// #endregion // #endregion
private toLogin(): void { private toLogin(): void {
this.notification.error(`未登录或登录已过期,请重新登录。`, ``); if (!this.notified) {
this.goTo(this.tokenSrv.login_url!); this.notified = true;
this.notification.error(`未登录或登录已过期,请重新登录。`, ``);
this.goTo(this.tokenSrv.login_url!);
}
} }
private handleData(ev: HttpResponseBase, req: HttpRequest<any>, next: HttpHandler): Observable<any> { private handleData(ev: HttpResponseBase, req: HttpRequest<any>, next: HttpHandler): Observable<any> {
...@@ -213,10 +234,7 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -213,10 +234,7 @@ export class DefaultInterceptor implements HttpInterceptor {
break; break;
default: default:
if (ev instanceof HttpErrorResponse) { if (ev instanceof HttpErrorResponse) {
console.warn( console.warn('未可知错误,大部分是由于后端不支持跨域CORS或无效配置引起.', ev);
'未可知错误,大部分是由于后端不支持跨域CORS或无效配置引起,请参考 https://ng-alain.com/docs/server 解决跨域问题',
ev
);
} }
break; break;
} }
...@@ -237,6 +255,8 @@ export class DefaultInterceptor implements HttpInterceptor { ...@@ -237,6 +255,8 @@ export class DefaultInterceptor implements HttpInterceptor {
if (jwtAuthn !== null) { if (jwtAuthn !== null) {
res['Authorization'] = `Bearer ${jwtAuthn.token}`; res['Authorization'] = `Bearer ${jwtAuthn.token}`;
} }
res['hostname'] = window.location.hostname;
res['AuthServer'] = 'MaxKey';
return res; return res;
} }
......
...@@ -55,7 +55,7 @@ maxkey.app.issuer =CN=ConSec,CN=COM,CN=SH ...@@ -55,7 +55,7 @@ maxkey.app.issuer =CN=ConSec,CN=COM,CN=SH
maxkey.session.timeout =${SERVER_SESSION_TIMEOUT:1800} maxkey.session.timeout =${SERVER_SESSION_TIMEOUT:1800}
maxkey.auth.jwt.issuer =${maxkey.server.uri} maxkey.auth.jwt.issuer =${maxkey.server.uri}
maxkey.auth.jwt.expires =60 maxkey.auth.jwt.expires =600
maxkey.auth.jwt.secret =7heM-14BtxjyKPuH3ITIm7q2-ps5MuBirWCsrrdbzzSAOuSPrbQYiaJ54AeA0uH2XdkYy3hHAkTFIsieGkyqxOJZ_dQzrCbaYISH9rhUZAKYx8tUY0wkE4ArOC6LqHDJarR6UIcMsARakK9U4dhoOPO1cj74XytemI-w6ACYfzRUn_Rn4e-CQMcnD1C56oNEukwalf06xVgXl41h6K8IBEzLVod58y_VfvFn-NGWpNG0fy_Qxng6dg8Dgva2DobvzMN2eejHGLGB-x809MvC4zbG7CKNVlcrzMYDt2Gt2sOVDrt2l9YqJNfgaLFjrOEVw5cuXemGkX1MvHj6TAsbLg maxkey.auth.jwt.secret =7heM-14BtxjyKPuH3ITIm7q2-ps5MuBirWCsrrdbzzSAOuSPrbQYiaJ54AeA0uH2XdkYy3hHAkTFIsieGkyqxOJZ_dQzrCbaYISH9rhUZAKYx8tUY0wkE4ArOC6LqHDJarR6UIcMsARakK9U4dhoOPO1cj74XytemI-w6ACYfzRUn_Rn4e-CQMcnD1C56oNEukwalf06xVgXl41h6K8IBEzLVod58y_VfvFn-NGWpNG0fy_Qxng6dg8Dgva2DobvzMN2eejHGLGB-x809MvC4zbG7CKNVlcrzMYDt2Gt2sOVDrt2l9YqJNfgaLFjrOEVw5cuXemGkX1MvHj6TAsbLg
maxkey.auth.jwt.refresh.secret =7heM-14BtxjyKPuH3ITIm7q2-ps5MuBirWCsrrdbzzSAOuSPrbQYiaJ54AeA0uH2XdkYy3hHAkTFIsieGkyqxOJZ_dQzrCbaYISH9rhUZAKYx8tUY0wkE4ArOC6LqHDJarR6UIcMsARakK9U4dhoOPO1cj74XytemI-w6ACYfzRUn_Rn4e-CQMcnD1C56oNEukwalf06xVgXl41h6K8IBEzLVod58y_VfvFn-NGWpNG0fy_Qxng6dg8Dgva2DobvzMN2eejHGLGB-x809MvC4zbG7CKNVlcrzMYDt2Gt2sOVDrt2l9YqJNfgaLFjrOEVw5cuXemGkX1MvHj6TAsbLg maxkey.auth.jwt.refresh.secret =7heM-14BtxjyKPuH3ITIm7q2-ps5MuBirWCsrrdbzzSAOuSPrbQYiaJ54AeA0uH2XdkYy3hHAkTFIsieGkyqxOJZ_dQzrCbaYISH9rhUZAKYx8tUY0wkE4ArOC6LqHDJarR6UIcMsARakK9U4dhoOPO1cj74XytemI-w6ACYfzRUn_Rn4e-CQMcnD1C56oNEukwalf06xVgXl41h6K8IBEzLVod58y_VfvFn-NGWpNG0fy_Qxng6dg8Dgva2DobvzMN2eejHGLGB-x809MvC4zbG7CKNVlcrzMYDt2Gt2sOVDrt2l9YqJNfgaLFjrOEVw5cuXemGkX1MvHj6TAsbLg
############################################################################ ############################################################################
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册