Complete refresh token logic

pull/146/head
johnniang 2019-04-29 18:19:40 +08:00
parent 12a6a62794
commit f5701691fb
4 changed files with 70 additions and 19 deletions

View File

@ -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;
} }

View File

@ -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);
}
} }

View File

@ -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);
} }

View File

@ -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;
}
} }