Complete admin login api

pull/137/head
johnniang 2019-03-28 01:16:15 +08:00
parent 42032e3b78
commit dd2caca58d
9 changed files with 102 additions and 18 deletions

View File

@ -81,7 +81,7 @@ public class HaloConfiguration {
public FilterRegistrationBean<AdminAuthenticationFilter> adminAuthenticationFilter(HaloProperties haloProperties,
ObjectMapper objectMapper,
StringCacheStore cacheStore) {
AdminAuthenticationFilter adminFilter = new AdminAuthenticationFilter(cacheStore);
AdminAuthenticationFilter adminFilter = new AdminAuthenticationFilter(cacheStore, "/admin/api/login");
// Set failure handler
adminFilter.setFailureHandler(new AdminAuthenticationFailureHandler(haloProperties.getProductionEnv(), objectMapper));

View File

@ -31,8 +31,6 @@ public class UserOutputDTO implements OutputConverter<UserOutputDTO, User> {
private String description;
private Date expireTime;
private Date createTime;
private Date updateTime;

View File

@ -0,0 +1,27 @@
package cc.ryanc.halo.model.params;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
/**
* Login param.
*
* @author johnniang
* @date 3/28/19
*/
@Data
@ToString
public class LoginParam {
@NotBlank(message = "Username or email must not be blank")
@Size(max = 255, message = "Length of username or email must not be more than {max}")
private String username;
@NotBlank(message = "Password must not be blank")
@Size(max = 100, message = "Length of password must not be more than {max}")
private String password;
}

View File

@ -12,6 +12,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;
@ -20,6 +21,9 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
/**
@ -48,8 +52,14 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
private final StringCacheStore cacheStore;
public AdminAuthenticationFilter(StringCacheStore cacheStore) {
private final Collection<String> excludeUrlPatterns;
private final AntPathMatcher antPathMatcher;
public AdminAuthenticationFilter(StringCacheStore cacheStore, String... excludeUrls) {
this.cacheStore = cacheStore;
this.excludeUrlPatterns = excludeUrls == null ? Collections.emptyList() : Collections.unmodifiableCollection(Arrays.asList(excludeUrls));
antPathMatcher = new AntPathMatcher();
}
@Override
@ -93,6 +103,11 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
failureHandler.onFailure(request, response, new AuthenticationException("You have to login before accessing admin api"));
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
return excludeUrlPatterns.stream().anyMatch(p -> antPathMatcher.match(p, request.getServletPath()));
}
public void setFailureHandler(AuthenticationFailureHandler failureHandler) {
this.failureHandler = failureHandler;
}
@ -117,4 +132,5 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
return token;
}
}

View File

@ -2,7 +2,9 @@ package cc.ryanc.halo.security.support;
import cc.ryanc.halo.exception.AuthenticationException;
import cc.ryanc.halo.model.entity.User;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.lang.NonNull;
@ -13,6 +15,8 @@ import org.springframework.lang.NonNull;
*/
@ToString
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class UserDetail {
private User user;

View File

@ -6,6 +6,7 @@ import cc.ryanc.halo.model.params.UserParam;
import cc.ryanc.halo.service.base.CrudService;
import org.springframework.lang.NonNull;
import javax.servlet.http.HttpSession;
import java.util.Optional;
/**
@ -70,10 +71,11 @@ public interface UserService extends CrudService<User, Integer> {
*
* @param key username or email must not be blank
* @param password password must not be blank
* @param httpSession http session must not be null
* @return user info
*/
@NonNull
User login(@NonNull String key, @NonNull String password);
User login(@NonNull String key, @NonNull String password, @NonNull HttpSession httpSession);
/**
* Updates user password.

View File

@ -6,6 +6,8 @@ import cc.ryanc.halo.exception.NotFoundException;
import cc.ryanc.halo.model.entity.User;
import cc.ryanc.halo.model.params.UserParam;
import cc.ryanc.halo.repository.UserRepository;
import cc.ryanc.halo.security.filter.AdminAuthenticationFilter;
import cc.ryanc.halo.security.support.UserDetail;
import cc.ryanc.halo.service.UserService;
import cc.ryanc.halo.service.base.AbstractCrudService;
import cc.ryanc.halo.utils.DateUtils;
@ -15,6 +17,7 @@ import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.servlet.http.HttpSession;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@ -72,9 +75,10 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
}
@Override
public User login(String key, String password) {
public User login(String key, String password, HttpSession httpSession) {
Assert.hasText(key, "Username or email must not be blank");
Assert.hasText(password, "Password must not be blank");
Assert.notNull(httpSession, "Http session must not be null");
// Ger user by username
User user = Validator.isEmail(key) ? getByEmailOfNonNull(key) : getByUsernameOfNonNull(key);
@ -105,7 +109,8 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
throw new BadRequestException("账号或者密码错误,您还有" + (MAX_LOGIN_TRY - loginFailureCount) + "次机会");
}
// TODO Set session or cache token
// Set session
httpSession.setAttribute(AdminAuthenticationFilter.ADMIN_SESSION_KEY, new UserDetail(user));
return user;
}

View File

@ -1,17 +1,17 @@
package cc.ryanc.halo.web.controller.admin.api;
import cc.ryanc.halo.model.dto.CountOutputDTO;
import cc.ryanc.halo.model.dto.UserOutputDTO;
import cc.ryanc.halo.model.enums.BlogProperties;
import cc.ryanc.halo.model.enums.PostStatus;
import cc.ryanc.halo.model.enums.PostType;
import cc.ryanc.halo.service.AttachmentService;
import cc.ryanc.halo.service.CommentService;
import cc.ryanc.halo.service.OptionService;
import cc.ryanc.halo.service.PostService;
import cc.ryanc.halo.model.params.LoginParam;
import cc.ryanc.halo.service.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
/**
* Admin controller.
@ -31,11 +31,18 @@ public class AdminController {
private final OptionService optionService;
public AdminController(PostService postService, AttachmentService attachmentService, CommentService commentService, OptionService optionService) {
private final UserService userService;
public AdminController(PostService postService,
AttachmentService attachmentService,
CommentService commentService,
OptionService optionService,
UserService userService) {
this.postService = postService;
this.attachmentService = attachmentService;
this.commentService = commentService;
this.optionService = optionService;
this.userService = userService;
}
@GetMapping("counts")
@ -48,4 +55,10 @@ public class AdminController {
countOutputDTO.setEstablishDays(Long.valueOf(optionService.getByProperty(BlogProperties.WIDGET_DAYCOUNT).orElse("0")));
return countOutputDTO;
}
@PostMapping("login")
@ApiOperation("Logins with session")
public UserOutputDTO login(@Valid @RequestBody LoginParam loginParam, HttpServletRequest request) {
return new UserOutputDTO().convertFrom(userService.login(loginParam.getUsername(), loginParam.getPassword(), request.getSession()));
}
}

View File

@ -0,0 +1,19 @@
package cc.ryanc.halo.utils;
import cn.hutool.crypto.digest.BCrypt;
import org.junit.Test;
/**
* BCrypt test.
*
* @author johnniang
* @date 3/28/19
*/
public class BcryptTest {
@Test
public void cryptTest() {
String cryptPassword = BCrypt.hashpw("opentest", BCrypt.gensalt());
System.out.println("Crypt password: " + cryptPassword);
}
}