mirror of https://github.com/halo-dev/halo
				
				
				
			Complete token authentication
							parent
							
								
									e580f4fa96
								
							
						
					
					
						commit
						7c6708d5f4
					
				| 
						 | 
					@ -91,6 +91,7 @@ public class InMemoryCacheStore extends StringCacheStore {
 | 
				
			||||||
        Assert.hasText(key, "Cache key must not be blank");
 | 
					        Assert.hasText(key, "Cache key must not be blank");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cacheContainer.remove(key);
 | 
					        cacheContainer.remove(key);
 | 
				
			||||||
 | 
					        log.debug("Removed key: [{}]", key);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,15 +4,11 @@ import io.swagger.annotations.ApiOperation;
 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
import org.springframework.web.bind.annotation.*;
 | 
					import org.springframework.web.bind.annotation.*;
 | 
				
			||||||
import run.halo.app.cache.lock.CacheLock;
 | 
					import run.halo.app.cache.lock.CacheLock;
 | 
				
			||||||
import run.halo.app.exception.BadRequestException;
 | 
					import run.halo.app.model.dto.StatisticDTO;
 | 
				
			||||||
import run.halo.app.model.dto.CountDTO;
 | 
					 | 
				
			||||||
import run.halo.app.model.params.LoginParam;
 | 
					import run.halo.app.model.params.LoginParam;
 | 
				
			||||||
import run.halo.app.security.context.SecurityContextHolder;
 | 
					 | 
				
			||||||
import run.halo.app.security.filter.AdminAuthenticationFilter;
 | 
					 | 
				
			||||||
import run.halo.app.security.token.AuthToken;
 | 
					import run.halo.app.security.token.AuthToken;
 | 
				
			||||||
import run.halo.app.service.AdminService;
 | 
					import run.halo.app.service.AdminService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.servlet.http.HttpServletRequest;
 | 
					 | 
				
			||||||
import javax.validation.Valid;
 | 
					import javax.validation.Valid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -39,7 +35,7 @@ public class AdminController {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @GetMapping("counts")
 | 
					    @GetMapping("counts")
 | 
				
			||||||
    @ApiOperation("Gets count info")
 | 
					    @ApiOperation("Gets count info")
 | 
				
			||||||
    public CountDTO getCount() {
 | 
					    public StatisticDTO getCount() {
 | 
				
			||||||
        return adminService.getCount();
 | 
					        return adminService.getCount();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,17 +48,7 @@ public class AdminController {
 | 
				
			||||||
    @PostMapping("logout")
 | 
					    @PostMapping("logout")
 | 
				
			||||||
    @ApiOperation("Logs out (Clear session)")
 | 
					    @ApiOperation("Logs out (Clear session)")
 | 
				
			||||||
    @CacheLock
 | 
					    @CacheLock
 | 
				
			||||||
    public void logout(HttpServletRequest request) {
 | 
					    public void logout() {
 | 
				
			||||||
        adminService.clearAuthentication();
 | 
					        adminService.clearToken();
 | 
				
			||||||
        // Check if the current is logging in
 | 
					 | 
				
			||||||
        boolean authenticated = SecurityContextHolder.getContext().isAuthenticated();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!authenticated) {
 | 
					 | 
				
			||||||
            throw new BadRequestException("You haven't logged in yet, so you can't log out");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        request.getSession().removeAttribute(AdminAuthenticationFilter.ADMIN_SESSION_KEY);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        log.info("You have been logged out, Welcome to you next time!");
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,13 +3,13 @@ package run.halo.app.model.dto;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Count output DTO.
 | 
					 * Statistic DTO.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author johnniang
 | 
					 * @author johnniang
 | 
				
			||||||
 * @date 3/19/19
 | 
					 * @date 3/19/19
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
public class CountDTO {
 | 
					public class StatisticDTO {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private long postCount;
 | 
					    private long postCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ import run.halo.app.security.authentication.AuthenticationImpl;
 | 
				
			||||||
import run.halo.app.security.context.SecurityContextHolder;
 | 
					import run.halo.app.security.context.SecurityContextHolder;
 | 
				
			||||||
import run.halo.app.security.context.SecurityContextImpl;
 | 
					import run.halo.app.security.context.SecurityContextImpl;
 | 
				
			||||||
import run.halo.app.security.support.UserDetail;
 | 
					import run.halo.app.security.support.UserDetail;
 | 
				
			||||||
 | 
					import run.halo.app.security.util.SecurityUtils;
 | 
				
			||||||
import run.halo.app.service.UserService;
 | 
					import run.halo.app.service.UserService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.servlet.FilterChain;
 | 
					import javax.servlet.FilterChain;
 | 
				
			||||||
| 
						 | 
					@ -37,6 +38,16 @@ public class AdminAuthenticationFilter extends AbstractAuthenticationFilter {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public final static String ADMIN_SESSION_KEY = "halo.admin.session";
 | 
					    public final static String ADMIN_SESSION_KEY = "halo.admin.session";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Access token cache prefix.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public final static String TOKEN_ACCESS_CACHE_PREFIX = "halo.admin.access.token.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Refresh token cache prefix.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public final static String TOKEN_REFRESH_CACHE_PREFIX = "halo.admin.refresh.token.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Admin token header name.
 | 
					     * Admin token header name.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
| 
						 | 
					@ -82,20 +93,25 @@ public class AdminAuthenticationFilter extends AbstractAuthenticationFilter {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (StringUtils.isNotBlank(token)) {
 | 
					        if (StringUtils.isNotBlank(token)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Valid the token
 | 
					            // Get user id from cache
 | 
				
			||||||
            Optional<UserDetail> optionalUserDetail = cacheStore.getAny(token, UserDetail.class);
 | 
					            Optional<Integer> optionalUserId = cacheStore.getAny(SecurityUtils.buildTokenAccessKey(token), Integer.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!optionalUserDetail.isPresent()) {
 | 
					            if (!optionalUserId.isPresent()) {
 | 
				
			||||||
                getFailureHandler().onFailure(request, response, new AuthenticationException("The token has been expired or not exist").setErrorData(token));
 | 
					                getFailureHandler().onFailure(request, response, new AuthenticationException("The token has been expired or not exist").setErrorData(token));
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            UserDetail userDetail = optionalUserDetail.get();
 | 
					            // Get the user
 | 
				
			||||||
 | 
					            User user = userService.getById(optionalUserId.get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Build user detail
 | 
				
			||||||
 | 
					            UserDetail userDetail = new UserDetail(user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Set security
 | 
					            // Set security
 | 
				
			||||||
            SecurityContextHolder.setContext(new SecurityContextImpl(new AuthenticationImpl(userDetail)));
 | 
					            SecurityContextHolder.setContext(new SecurityContextImpl(new AuthenticationImpl(userDetail)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            filterChain.doFilter(request, response);
 | 
					            filterChain.doFilter(request, response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,50 @@
 | 
				
			||||||
 | 
					package run.halo.app.security.util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.lang.NonNull;
 | 
				
			||||||
 | 
					import org.springframework.util.Assert;
 | 
				
			||||||
 | 
					import run.halo.app.model.entity.User;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static run.halo.app.security.filter.AdminAuthenticationFilter.TOKEN_ACCESS_CACHE_PREFIX;
 | 
				
			||||||
 | 
					import static run.halo.app.security.filter.AdminAuthenticationFilter.TOKEN_REFRESH_CACHE_PREFIX;
 | 
				
			||||||
 | 
					import static run.halo.app.service.AdminService.ACCESS_TOKEN_CACHE_PREFIX;
 | 
				
			||||||
 | 
					import static run.halo.app.service.AdminService.REFRESH_TOKEN_CACHE_PREFIX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Security utilities.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @author johnniang
 | 
				
			||||||
 | 
					 * @date 19-4-29
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class SecurityUtils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private SecurityUtils() {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @NonNull
 | 
				
			||||||
 | 
					    public static String buildAccessTokenKey(@NonNull User user) {
 | 
				
			||||||
 | 
					        Assert.notNull(user, "User must not be null");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ACCESS_TOKEN_CACHE_PREFIX + user.getId();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @NonNull
 | 
				
			||||||
 | 
					    public static String buildRefreshTokenKey(@NonNull User user) {
 | 
				
			||||||
 | 
					        Assert.notNull(user, "User must not be null");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return REFRESH_TOKEN_CACHE_PREFIX + user.getId();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @NonNull
 | 
				
			||||||
 | 
					    public static String buildTokenAccessKey(@NonNull String accessToken) {
 | 
				
			||||||
 | 
					        Assert.hasText(accessToken, "Access token must not be blank");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return TOKEN_ACCESS_CACHE_PREFIX + accessToken;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @NonNull
 | 
				
			||||||
 | 
					    public static String buildTokenRefreshKey(@NonNull String refreshToken) {
 | 
				
			||||||
 | 
					        Assert.hasText(refreshToken, "Refresh token must not be blank");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return TOKEN_REFRESH_CACHE_PREFIX + refreshToken;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
package run.halo.app.service;
 | 
					package run.halo.app.service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.lang.NonNull;
 | 
					import org.springframework.lang.NonNull;
 | 
				
			||||||
import run.halo.app.model.dto.CountDTO;
 | 
					import run.halo.app.model.dto.StatisticDTO;
 | 
				
			||||||
import run.halo.app.model.params.LoginParam;
 | 
					import run.halo.app.model.params.LoginParam;
 | 
				
			||||||
import run.halo.app.security.token.AuthToken;
 | 
					import run.halo.app.security.token.AuthToken;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,10 @@ import run.halo.app.security.token.AuthToken;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public interface AdminService {
 | 
					public interface AdminService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    String ACCESS_TOKEN_CACHE_PREFIX = "halo.admin.access_token.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    String REFRESH_TOKEN_CACHE_PREFIX = "halo.admin.refresh_token.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Authenticates.
 | 
					     * Authenticates.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					@ -25,7 +29,7 @@ public interface AdminService {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Clears authentication.
 | 
					     * Clears authentication.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void clearAuthentication();
 | 
					    void clearToken();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get system counts.
 | 
					     * Get system counts.
 | 
				
			||||||
| 
						 | 
					@ -33,5 +37,5 @@ public interface AdminService {
 | 
				
			||||||
     * @return count dto
 | 
					     * @return count dto
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @NonNull
 | 
					    @NonNull
 | 
				
			||||||
    CountDTO getCount();
 | 
					    StatisticDTO getCount();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,13 @@
 | 
				
			||||||
package run.halo.app.service;
 | 
					package run.halo.app.service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.lang.NonNull;
 | 
					import org.springframework.lang.NonNull;
 | 
				
			||||||
 | 
					import org.springframework.lang.Nullable;
 | 
				
			||||||
 | 
					import run.halo.app.exception.ForbiddenException;
 | 
				
			||||||
import run.halo.app.exception.NotFoundException;
 | 
					import run.halo.app.exception.NotFoundException;
 | 
				
			||||||
import run.halo.app.model.entity.User;
 | 
					import run.halo.app.model.entity.User;
 | 
				
			||||||
import run.halo.app.model.params.UserParam;
 | 
					import run.halo.app.model.params.UserParam;
 | 
				
			||||||
import run.halo.app.service.base.CrudService;
 | 
					import run.halo.app.service.base.CrudService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.servlet.http.HttpSession;
 | 
					 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -107,4 +108,21 @@ public interface UserService extends CrudService<User, Integer> {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @NonNull
 | 
					    @NonNull
 | 
				
			||||||
    User createBy(@NonNull UserParam userParam);
 | 
					    User createBy(@NonNull UserParam userParam);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The user must not expire.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param user user info must not be null
 | 
				
			||||||
 | 
					     * @throws ForbiddenException throws if the given user has been expired
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void mustNotExpire(@NonNull User user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Checks the password is match the user password.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param user          user info must not be null
 | 
				
			||||||
 | 
					     * @param plainPassword plain password
 | 
				
			||||||
 | 
					     * @return true if the given password is match the user password; false otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    boolean passwordMatch(@NonNull User user, @Nullable String plainPassword);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,17 +1,24 @@
 | 
				
			||||||
package run.halo.app.service.impl;
 | 
					package run.halo.app.service.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.hutool.core.lang.Validator;
 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
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;
 | 
				
			||||||
import run.halo.app.exception.BadRequestException;
 | 
					import run.halo.app.exception.BadRequestException;
 | 
				
			||||||
import run.halo.app.model.dto.CountDTO;
 | 
					import run.halo.app.model.dto.StatisticDTO;
 | 
				
			||||||
 | 
					import run.halo.app.model.entity.User;
 | 
				
			||||||
import run.halo.app.model.enums.CommentStatus;
 | 
					import run.halo.app.model.enums.CommentStatus;
 | 
				
			||||||
import run.halo.app.model.enums.PostStatus;
 | 
					import run.halo.app.model.enums.PostStatus;
 | 
				
			||||||
import run.halo.app.model.params.LoginParam;
 | 
					import run.halo.app.model.params.LoginParam;
 | 
				
			||||||
 | 
					import run.halo.app.security.authentication.Authentication;
 | 
				
			||||||
import run.halo.app.security.context.SecurityContextHolder;
 | 
					import run.halo.app.security.context.SecurityContextHolder;
 | 
				
			||||||
import run.halo.app.security.token.AuthToken;
 | 
					import run.halo.app.security.token.AuthToken;
 | 
				
			||||||
 | 
					import run.halo.app.security.util.SecurityUtils;
 | 
				
			||||||
import run.halo.app.service.*;
 | 
					import run.halo.app.service.*;
 | 
				
			||||||
 | 
					import run.halo.app.utils.HaloUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.concurrent.TimeUnit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Admin service implementation.
 | 
					 * Admin service implementation.
 | 
				
			||||||
| 
						 | 
					@ -69,42 +76,92 @@ public class AdminServiceImpl implements AdminService {
 | 
				
			||||||
    public AuthToken authenticate(LoginParam loginParam) {
 | 
					    public AuthToken authenticate(LoginParam loginParam) {
 | 
				
			||||||
        Assert.notNull(loginParam, "Login param must not be null");
 | 
					        Assert.notNull(loginParam, "Login param must not be null");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return null;
 | 
					        if (SecurityContextHolder.getContext().isAuthenticated()) {
 | 
				
			||||||
 | 
					            // If the user has been logged in
 | 
				
			||||||
 | 
					            throw new BadRequestException("您已经登录,无需重复登录");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        String username = loginParam.getUsername();
 | 
				
			||||||
 | 
					        User user = Validator.isEmail(username) ?
 | 
				
			||||||
 | 
					                userService.getByEmailOfNonNull(username) : userService.getByUsernameOfNonNull(username);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        userService.mustNotExpire(user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!userService.passwordMatch(user, loginParam.getPassword())) {
 | 
				
			||||||
 | 
					            // If the password is mismatch
 | 
				
			||||||
 | 
					            throw new BadRequestException("Username or password is incorrect");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Generate new token
 | 
				
			||||||
 | 
					        AuthToken token = new AuthToken();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int expiredIn = 24 * 3600;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        token.setAccessToken(HaloUtils.randomUUIDWithoutDash());
 | 
				
			||||||
 | 
					        token.setExpiredIn(expiredIn);
 | 
				
			||||||
 | 
					        token.setRefreshToken(HaloUtils.randomUUIDWithoutDash());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Cache those tokens, just for clearing
 | 
				
			||||||
 | 
					        cacheStore.putAny(SecurityUtils.buildAccessTokenKey(user), token.getAccessToken(), 30, TimeUnit.DAYS);
 | 
				
			||||||
 | 
					        cacheStore.putAny(SecurityUtils.buildRefreshTokenKey(user), token.getRefreshToken(), 30, TimeUnit.DAYS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Cache those tokens with user id
 | 
				
			||||||
 | 
					        cacheStore.putAny(SecurityUtils.buildTokenAccessKey(token.getAccessToken()), user.getId(), expiredIn, TimeUnit.SECONDS);
 | 
				
			||||||
 | 
					        cacheStore.putAny(SecurityUtils.buildTokenRefreshKey(token.getRefreshToken()), user.getId(), 30, TimeUnit.DAYS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return token;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void clearAuthentication() {
 | 
					    public void clearToken() {
 | 
				
			||||||
        // Check if the current is logging in
 | 
					        // Check if the current is logging in
 | 
				
			||||||
        boolean authenticated = SecurityContextHolder.getContext().isAuthenticated();
 | 
					        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!authenticated) {
 | 
					        if (authentication == null) {
 | 
				
			||||||
            throw new BadRequestException("You haven't logged in yet, so you can't log out");
 | 
					            throw new BadRequestException("You haven't logged in yet, so you can't log out");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get current user
 | 
				
			||||||
 | 
					        User user = authentication.getDetail().getUser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Clear access token
 | 
				
			||||||
 | 
					        cacheStore.getAny(SecurityUtils.buildAccessTokenKey(user), String.class).ifPresent(accessToken -> {
 | 
				
			||||||
 | 
					            // Delete token
 | 
				
			||||||
 | 
					            cacheStore.delete(SecurityUtils.buildTokenAccessKey(accessToken));
 | 
				
			||||||
 | 
					            cacheStore.delete(SecurityUtils.buildAccessTokenKey(user));
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Clear refresh token
 | 
				
			||||||
 | 
					        cacheStore.getAny(SecurityUtils.buildRefreshTokenKey(user), String.class).ifPresent(refreshToken -> {
 | 
				
			||||||
 | 
					            cacheStore.delete(SecurityUtils.buildTokenRefreshKey(refreshToken));
 | 
				
			||||||
 | 
					            cacheStore.delete(SecurityUtils.buildRefreshTokenKey(user));
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        log.info("You have been logged out, looking forward to your next visit!");
 | 
					        log.info("You have been logged out, looking forward to your next visit!");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public CountDTO getCount() {
 | 
					    public StatisticDTO getCount() {
 | 
				
			||||||
        CountDTO countDTO = new CountDTO();
 | 
					        StatisticDTO statisticDTO = new StatisticDTO();
 | 
				
			||||||
        countDTO.setPostCount(postService.countByStatus(PostStatus.PUBLISHED));
 | 
					        statisticDTO.setPostCount(postService.countByStatus(PostStatus.PUBLISHED));
 | 
				
			||||||
        countDTO.setAttachmentCount(attachmentService.count());
 | 
					        statisticDTO.setAttachmentCount(attachmentService.count());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Handle comment count
 | 
					        // Handle comment count
 | 
				
			||||||
        long postCommentCount = postCommentService.countByStatus(CommentStatus.PUBLISHED);
 | 
					        long postCommentCount = postCommentService.countByStatus(CommentStatus.PUBLISHED);
 | 
				
			||||||
        long sheetCommentCount = sheetCommentService.countByStatus(CommentStatus.PUBLISHED);
 | 
					        long sheetCommentCount = sheetCommentService.countByStatus(CommentStatus.PUBLISHED);
 | 
				
			||||||
        long journalCommentCount = journalCommentService.countByStatus(CommentStatus.PUBLISHED);
 | 
					        long journalCommentCount = journalCommentService.countByStatus(CommentStatus.PUBLISHED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        countDTO.setCommentCount(postCommentCount + sheetCommentCount + journalCommentCount);
 | 
					        statisticDTO.setCommentCount(postCommentCount + sheetCommentCount + journalCommentCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        long birthday = optionService.getBirthday();
 | 
					        long birthday = optionService.getBirthday();
 | 
				
			||||||
        long days = (System.currentTimeMillis() - birthday) / (1000 * 24 * 3600);
 | 
					        long days = (System.currentTimeMillis() - birthday) / (1000 * 24 * 3600);
 | 
				
			||||||
        countDTO.setEstablishDays(days);
 | 
					        statisticDTO.setEstablishDays(days);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        countDTO.setLinkCount(linkService.count());
 | 
					        statisticDTO.setLinkCount(linkService.count());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        countDTO.setVisitCount(postService.countVisit() + sheetService.countVisit());
 | 
					        statisticDTO.setVisitCount(postService.countVisit() + sheetService.countVisit());
 | 
				
			||||||
        countDTO.setLikeCount(postService.countLike() + sheetService.countLike());
 | 
					        statisticDTO.setLikeCount(postService.countLike() + sheetService.countLike());
 | 
				
			||||||
        return countDTO;
 | 
					        return statisticDTO;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ package run.halo.app.service.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import cn.hutool.core.lang.Validator;
 | 
					import cn.hutool.core.lang.Validator;
 | 
				
			||||||
import cn.hutool.crypto.digest.BCrypt;
 | 
					import cn.hutool.crypto.digest.BCrypt;
 | 
				
			||||||
 | 
					import org.apache.commons.lang3.StringUtils;
 | 
				
			||||||
import org.springframework.context.ApplicationEventPublisher;
 | 
					import org.springframework.context.ApplicationEventPublisher;
 | 
				
			||||||
import org.springframework.lang.NonNull;
 | 
					import org.springframework.lang.NonNull;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
| 
						 | 
					@ -12,6 +13,7 @@ import run.halo.app.cache.lock.CacheLock;
 | 
				
			||||||
import run.halo.app.event.logger.LogEvent;
 | 
					import run.halo.app.event.logger.LogEvent;
 | 
				
			||||||
import run.halo.app.event.user.UserUpdatedEvent;
 | 
					import run.halo.app.event.user.UserUpdatedEvent;
 | 
				
			||||||
import run.halo.app.exception.BadRequestException;
 | 
					import run.halo.app.exception.BadRequestException;
 | 
				
			||||||
 | 
					import run.halo.app.exception.ForbiddenException;
 | 
				
			||||||
import run.halo.app.exception.NotFoundException;
 | 
					import run.halo.app.exception.NotFoundException;
 | 
				
			||||||
import run.halo.app.model.entity.User;
 | 
					import run.halo.app.model.entity.User;
 | 
				
			||||||
import run.halo.app.model.enums.LogType;
 | 
					import run.halo.app.model.enums.LogType;
 | 
				
			||||||
| 
						 | 
					@ -205,6 +207,25 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
 | 
				
			||||||
        return create(user);
 | 
					        return create(user);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void mustNotExpire(User user) {
 | 
				
			||||||
 | 
					        Assert.notNull(user, "User must not be null");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Date now = DateUtils.now();
 | 
				
			||||||
 | 
					        if (user.getExpireTime() != null && user.getExpireTime().after(now)) {
 | 
				
			||||||
 | 
					            long seconds = TimeUnit.MILLISECONDS.toSeconds(user.getExpireTime().getTime() - now.getTime());
 | 
				
			||||||
 | 
					            // If expired
 | 
				
			||||||
 | 
					            throw new ForbiddenException("You have been temporarily disabled,please try again " + HaloUtils.timeFormat(seconds) + " later").setErrorData(seconds);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean passwordMatch(User user, String plainPassword) {
 | 
				
			||||||
 | 
					        Assert.notNull(user, "User must not be null");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return !StringUtils.isBlank(plainPassword) && BCrypt.checkpw(plainPassword, user.getPassword());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    @CacheLock
 | 
					    @CacheLock
 | 
				
			||||||
    public User create(User user) {
 | 
					    public User create(User user) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue