mirror of https://github.com/halo-dev/halo
Complete refresh token logic
parent
12a6a62794
commit
f5701691fb
|
@ -101,11 +101,10 @@ public class HaloConfiguration {
|
||||||
|
|
||||||
// Set failure handler
|
// Set failure handler
|
||||||
apiFilter.setFailureHandler(failureHandler);
|
apiFilter.setFailureHandler(failureHandler);
|
||||||
apiFilter.addExcludeUrlPatterns("/api/admin/*");
|
|
||||||
|
|
||||||
FilterRegistrationBean<ApiAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
|
FilterRegistrationBean<ApiAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
|
||||||
authenticationFilter.setFilter(apiFilter);
|
authenticationFilter.setFilter(apiFilter);
|
||||||
authenticationFilter.addUrlPatterns("/api/*");
|
authenticationFilter.addUrlPatterns("/api/content/*");
|
||||||
authenticationFilter.setOrder(0);
|
authenticationFilter.setOrder(0);
|
||||||
return authenticationFilter;
|
return authenticationFilter;
|
||||||
}
|
}
|
||||||
|
@ -125,17 +124,18 @@ public class HaloConfiguration {
|
||||||
// Config the admin filter
|
// Config the admin filter
|
||||||
adminAuthenticationFilter.addExcludeUrlPatterns(
|
adminAuthenticationFilter.addExcludeUrlPatterns(
|
||||||
"/api/admin/login",
|
"/api/admin/login",
|
||||||
|
"/api/admin/refresh/*",
|
||||||
"/api/admin/installations",
|
"/api/admin/installations",
|
||||||
"/api/admin/recoveries/migrations/*"
|
"/api/admin/recoveries/migrations/*"
|
||||||
);
|
);
|
||||||
adminAuthenticationFilter.addTryAuthUrlMethodPattern("/api/admin/comments", HttpMethod.POST.name());
|
adminAuthenticationFilter.addTryAuthUrlMethodPattern("/api/admin/comments", HttpMethod.POST.name());
|
||||||
adminAuthenticationFilter.addTryAuthUrlMethodPattern("/api/comments", HttpMethod.POST.name());
|
adminAuthenticationFilter.addTryAuthUrlMethodPattern("/api/content/comments", HttpMethod.POST.name());
|
||||||
adminAuthenticationFilter.setFailureHandler(
|
adminAuthenticationFilter.setFailureHandler(
|
||||||
failureHandler);
|
failureHandler);
|
||||||
|
|
||||||
FilterRegistrationBean<AdminAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
|
FilterRegistrationBean<AdminAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
|
||||||
authenticationFilter.setFilter(adminAuthenticationFilter);
|
authenticationFilter.setFilter(adminAuthenticationFilter);
|
||||||
authenticationFilter.addUrlPatterns("/api/admin/*", "/api/comments");
|
authenticationFilter.addUrlPatterns("/api/admin/*", "/api/content/comments");
|
||||||
authenticationFilter.setOrder(1);
|
authenticationFilter.setOrder(1);
|
||||||
return authenticationFilter;
|
return authenticationFilter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,4 +52,11 @@ public class AdminController {
|
||||||
public void logout() {
|
public void logout() {
|
||||||
adminService.clearToken();
|
adminService.clearToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("refresh/{refreshToken}")
|
||||||
|
@ApiOperation("Refreshes token")
|
||||||
|
@CacheLock
|
||||||
|
public AuthToken refresh(@PathVariable("refreshToken") String refreshToken) {
|
||||||
|
return adminService.refreshToken(refreshToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,4 +45,13 @@ public interface AdminService {
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
StatisticDTO getCount();
|
StatisticDTO getCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes token.
|
||||||
|
*
|
||||||
|
* @param refreshToken refresh token must not be blank
|
||||||
|
* @return authentication token
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
AuthToken refreshToken(@NonNull String refreshToken);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package run.halo.app.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.lang.Validator;
|
import cn.hutool.core.lang.Validator;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import run.halo.app.cache.StringCacheStore;
|
import run.halo.app.cache.StringCacheStore;
|
||||||
|
@ -93,21 +94,7 @@ public class AdminServiceImpl implements AdminService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate new token
|
// Generate new token
|
||||||
AuthToken token = new AuthToken();
|
return buildAuthToken(user);
|
||||||
|
|
||||||
token.setAccessToken(HaloUtils.randomUUIDWithoutDash());
|
|
||||||
token.setExpiredIn(ACCESS_TOKEN_EXPIRED_SECONDS);
|
|
||||||
token.setRefreshToken(HaloUtils.randomUUIDWithoutDash());
|
|
||||||
|
|
||||||
// Cache those tokens, just for clearing
|
|
||||||
cacheStore.putAny(SecurityUtils.buildAccessTokenKey(user), token.getAccessToken(), REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
|
|
||||||
cacheStore.putAny(SecurityUtils.buildRefreshTokenKey(user), token.getRefreshToken(), REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
|
|
||||||
|
|
||||||
// Cache those tokens with user id
|
|
||||||
cacheStore.putAny(SecurityUtils.buildTokenAccessKey(token.getAccessToken()), user.getId(), ACCESS_TOKEN_EXPIRED_SECONDS, TimeUnit.SECONDS);
|
|
||||||
cacheStore.putAny(SecurityUtils.buildTokenRefreshKey(token.getRefreshToken()), user.getId(), REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -162,4 +149,52 @@ public class AdminServiceImpl implements AdminService {
|
||||||
return statisticDTO;
|
return statisticDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthToken refreshToken(String refreshToken) {
|
||||||
|
Assert.hasText(refreshToken, "Refresh token must not be blank");
|
||||||
|
|
||||||
|
Integer userId = cacheStore.getAny(SecurityUtils.buildTokenRefreshKey(refreshToken), Integer.class)
|
||||||
|
.orElseThrow(() -> new BadRequestException("The refresh token may have been expired already"));
|
||||||
|
|
||||||
|
// Get user info
|
||||||
|
User user = userService.getById(userId);
|
||||||
|
|
||||||
|
// Remove all token
|
||||||
|
cacheStore.getAny(SecurityUtils.buildAccessTokenKey(user), String.class).ifPresent(accessToken -> {
|
||||||
|
cacheStore.delete(SecurityUtils.buildTokenAccessKey(accessToken));
|
||||||
|
});
|
||||||
|
cacheStore.delete(SecurityUtils.buildTokenRefreshKey(refreshToken));
|
||||||
|
cacheStore.delete(SecurityUtils.buildAccessTokenKey(user));
|
||||||
|
cacheStore.delete(SecurityUtils.buildRefreshTokenKey(user));
|
||||||
|
|
||||||
|
return buildAuthToken(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds authentication token.
|
||||||
|
*
|
||||||
|
* @param user user info must not be null
|
||||||
|
* @return authentication token
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private AuthToken buildAuthToken(@NonNull User user) {
|
||||||
|
Assert.notNull(user, "User must not be null");
|
||||||
|
|
||||||
|
// Generate new token
|
||||||
|
AuthToken token = new AuthToken();
|
||||||
|
|
||||||
|
token.setAccessToken(HaloUtils.randomUUIDWithoutDash());
|
||||||
|
token.setExpiredIn(ACCESS_TOKEN_EXPIRED_SECONDS);
|
||||||
|
token.setRefreshToken(HaloUtils.randomUUIDWithoutDash());
|
||||||
|
|
||||||
|
// Cache those tokens, just for clearing
|
||||||
|
cacheStore.putAny(SecurityUtils.buildAccessTokenKey(user), token.getAccessToken(), REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
|
||||||
|
cacheStore.putAny(SecurityUtils.buildRefreshTokenKey(user), token.getRefreshToken(), REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
|
||||||
|
|
||||||
|
// Cache those tokens with user id
|
||||||
|
cacheStore.putAny(SecurityUtils.buildTokenAccessKey(token.getAccessToken()), user.getId(), ACCESS_TOKEN_EXPIRED_SECONDS, TimeUnit.SECONDS);
|
||||||
|
cacheStore.putAny(SecurityUtils.buildTokenRefreshKey(token.getRefreshToken()), user.getId(), REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue