fix: 密码机制
This commit is contained in:
parent
88f97a6896
commit
8c3048316a
@ -5,9 +5,9 @@ import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RoleType {
|
||||
public enum RoleType implements NamedEnum {
|
||||
|
||||
PC("PC端"), MOBILE("移动端");
|
||||
|
||||
private String name;
|
||||
private final String name;
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import lombok.Getter;
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum UserStatus {
|
||||
public enum UserStatus implements NamedEnum {
|
||||
|
||||
NORMAL("正常状态"), LOCKED("已锁定"), DISABLED("已禁用"), EXPIRED("已过期");
|
||||
|
||||
private String name;
|
||||
private final String name;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import java.util.Map;
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum UserType {
|
||||
public enum UserType implements NamedEnum {
|
||||
|
||||
SUPER_ADMIN("超级管理员"), ADMIN("管理员"), VIP("会员"), USER("非会员");
|
||||
|
||||
@ -25,7 +25,7 @@ public enum UserType {
|
||||
aliasMap.put("user", USER);
|
||||
}
|
||||
|
||||
private String name;
|
||||
private final String name;
|
||||
|
||||
public static UserType getByAlias(String alias) {
|
||||
return aliasMap.getOrDefault(alias, USER);
|
||||
|
@ -23,13 +23,13 @@ public interface IUser {
|
||||
|
||||
void setName(String name);
|
||||
|
||||
UserType getUserType();
|
||||
UserType getType();
|
||||
|
||||
void setUserType(UserType userType);
|
||||
void setType(UserType type);
|
||||
|
||||
UserStatus getUserStatus();
|
||||
UserStatus getStatus();
|
||||
|
||||
void setUserStatus(UserStatus userStatus);
|
||||
void setStatus(UserStatus status);
|
||||
|
||||
String getPhone();
|
||||
|
||||
|
@ -10,6 +10,8 @@ import java.util.List;
|
||||
@Setter
|
||||
public abstract class TreeDomain<T extends TreeDomain<T>> extends AuditDomain {
|
||||
|
||||
public static final String ROOT = "0";
|
||||
|
||||
// 父id,顶级是0
|
||||
private String parentId;
|
||||
|
||||
|
@ -28,12 +28,12 @@ public class User extends AuditDomain implements IUser {
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private UserType userType;
|
||||
private UserType type;
|
||||
|
||||
/**
|
||||
* 用户状态
|
||||
*/
|
||||
private UserStatus userStatus;
|
||||
private UserStatus status;
|
||||
|
||||
/**
|
||||
* 冗余的电话号码
|
||||
@ -83,7 +83,6 @@ public class User extends AuditDomain implements IUser {
|
||||
/**
|
||||
* 微信openId
|
||||
*/
|
||||
@Indexed(unique = true)
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
|
@ -5,9 +5,7 @@ import com.flyfish.framework.config.properties.SecurityProperties;
|
||||
import com.flyfish.framework.configuration.jwt.JwtSecurityContextRepository;
|
||||
import com.flyfish.framework.configuration.jwt.TokenProvider;
|
||||
import com.flyfish.framework.domain.UserQo;
|
||||
import com.flyfish.framework.domain.po.Role;
|
||||
import com.flyfish.framework.domain.po.User;
|
||||
import com.flyfish.framework.enums.RoleType;
|
||||
import com.flyfish.framework.enums.UserStatus;
|
||||
import com.flyfish.framework.enums.UserType;
|
||||
import com.flyfish.framework.handler.JsonAuthenticationFailureHandler;
|
||||
@ -35,8 +33,6 @@ import org.springframework.security.web.server.context.ServerSecurityContextRepo
|
||||
import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author wangyu
|
||||
*/
|
||||
@ -59,7 +55,6 @@ public class WebSecurityConfig {
|
||||
return delegatingPasswordEncoder;
|
||||
}
|
||||
|
||||
|
||||
@ConditionalOnProperty(value = "jwt.enable", havingValue = "true")
|
||||
@Bean("contextRepository")
|
||||
public JwtSecurityContextRepository jwtSecurityContextRepository() {
|
||||
@ -121,24 +116,23 @@ public class WebSecurityConfig {
|
||||
* 默认的初始化
|
||||
*
|
||||
* @param userService 用户服务
|
||||
* @param passwordEncoder 密码
|
||||
* @return 结果
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(UserInitializer.class)
|
||||
public UserInitializer userInitializer(UserService userService, PasswordEncoder passwordEncoder) {
|
||||
public UserInitializer userInitializer(UserService userService) {
|
||||
return () -> {
|
||||
UserQo qo = new UserQo();
|
||||
qo.setUserType(UserType.SUPER_ADMIN.name());
|
||||
qo.setType(UserType.SUPER_ADMIN.name());
|
||||
if (userService.count(qo) == 0) {
|
||||
// 初始化用户
|
||||
User user = new User();
|
||||
user.setUsername("admin");
|
||||
user.setPassword(passwordEncoder.encode("admin123456"));
|
||||
user.setUserType(UserType.SUPER_ADMIN);
|
||||
user.setPassword("admin123456");
|
||||
user.setType(UserType.SUPER_ADMIN);
|
||||
user.setEnable(true);
|
||||
user.setApp(false);
|
||||
user.setUserStatus(UserStatus.NORMAL);
|
||||
user.setStatus(UserStatus.NORMAL);
|
||||
user.setPhone("10000000000");
|
||||
user.setName("超级管理员");
|
||||
user.setCode("Administrator");
|
||||
|
@ -12,5 +12,5 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/permissions")
|
||||
public class PermissionController extends BaseController<Permission, PermissionQo> {
|
||||
public class PermissionController extends TreeController<Permission, PermissionQo> {
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class AdminUserDetails implements UserDetails, IUser {
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean isAdmin(User user) {
|
||||
return adminTypes.contains(user.getUserType());
|
||||
return adminTypes.contains(user.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,12 +59,12 @@ public class AdminUserDetails implements UserDetails, IUser {
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private UserType userType;
|
||||
private UserType type;
|
||||
|
||||
/**
|
||||
* 用户状态
|
||||
*/
|
||||
private UserStatus userStatus;
|
||||
private UserStatus status;
|
||||
|
||||
/**
|
||||
* 冗余的电话号码
|
||||
@ -126,7 +126,7 @@ public class AdminUserDetails implements UserDetails, IUser {
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public boolean isAccountNonExpired() {
|
||||
return adminTypes.contains(getUserType());
|
||||
return adminTypes.contains(getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,10 +3,13 @@ package com.flyfish.framework.domain;
|
||||
|
||||
import com.flyfish.framework.builder.CriteriaBuilder;
|
||||
import com.flyfish.framework.domain.base.NameLikeQo;
|
||||
import com.flyfish.framework.domain.base.TreeQo;
|
||||
import com.flyfish.framework.domain.po.Permission;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 权限查询实体
|
||||
*
|
||||
@ -14,12 +17,17 @@ import lombok.Setter;
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class PermissionQo extends NameLikeQo<Permission> {
|
||||
public class PermissionQo extends TreeQo<Permission> {
|
||||
|
||||
private Boolean admin;
|
||||
|
||||
private String parentId;
|
||||
|
||||
private List<String> parentIds;
|
||||
|
||||
@Override
|
||||
public CriteriaBuilder<Permission> criteriaBuilder() {
|
||||
return super.criteriaBuilder().with("admin");
|
||||
return super.criteriaBuilder().with("admin", "parentId")
|
||||
.with("parentIds", "parentId", CriteriaBuilder.Builders.IN);
|
||||
}
|
||||
}
|
||||
|
@ -12,14 +12,18 @@ import lombok.*;
|
||||
@NoArgsConstructor
|
||||
public class UserQo extends NameLikeQo<User> {
|
||||
|
||||
private String userType;
|
||||
private String type;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private String phone;
|
||||
|
||||
private String status;
|
||||
|
||||
@Override
|
||||
public CriteriaBuilder<User> criteriaBuilder() {
|
||||
return super.criteriaBuilder().with("userType", "username", "password");
|
||||
return super.criteriaBuilder().with("type", "username", "password", "phone", "status");
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
@ -45,13 +45,13 @@ public class MongoUserDetailsServiceImpl implements MongoUserDetailsService {
|
||||
checkMap = new HashMap<>();
|
||||
// 初始化用户校验规则
|
||||
checkMap.put(user -> null != user.getEnable() && !user.getEnable() ||
|
||||
user.getUserStatus() == UserStatus.DISABLED, () -> new DisabledException("用户被禁用"));
|
||||
checkMap.put(user -> user.getUserStatus() == UserStatus.LOCKED,
|
||||
user.getStatus() == UserStatus.DISABLED, () -> new DisabledException("用户被禁用"));
|
||||
checkMap.put(user -> user.getStatus() == UserStatus.LOCKED,
|
||||
() -> new LockedException("账户已经锁定!请联系管理员修改密码!"));
|
||||
}
|
||||
|
||||
private final UserService service;
|
||||
private final ReactiveUserService userService;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
@Resource
|
||||
private ServerSecurityContextRepository contextRepository;
|
||||
@ -62,7 +62,7 @@ public class MongoUserDetailsServiceImpl implements MongoUserDetailsService {
|
||||
private void init() {
|
||||
UserDetailsRepositoryReactiveAuthenticationManager manager =
|
||||
new UserDetailsRepositoryReactiveAuthenticationManager(this);
|
||||
manager.setPasswordEncoder(NoOpPasswordEncoder.getInstance());
|
||||
manager.setPasswordEncoder(passwordEncoder);
|
||||
authenticationManager = manager;
|
||||
}
|
||||
|
||||
@ -148,4 +148,24 @@ public class MongoUserDetailsServiceImpl implements MongoUserDetailsService {
|
||||
.flatMap(context -> contextRepository.save(exchange, context));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 发生错误时的处理
|
||||
*
|
||||
* @param exchange 交换
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public Mono<User> error(ServerWebExchange exchange) {
|
||||
return exchange.getFormData().flatMap(data -> userService.findByUsername(data.getFirst("username")))
|
||||
.flatMap(user -> {
|
||||
User updating = new User();
|
||||
updating.setId(user.getId());
|
||||
updating.setErrorCount(user.getErrorCount() + 1);
|
||||
if (updating.getErrorCount() >= 5) {
|
||||
updating.setStatus(UserStatus.LOCKED);
|
||||
}
|
||||
return userService.updateSelectiveById(updating);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ package com.flyfish.framework.service;
|
||||
|
||||
import com.flyfish.framework.domain.base.Qo;
|
||||
import com.flyfish.framework.domain.po.User;
|
||||
import com.flyfish.framework.enums.UserType;
|
||||
import com.flyfish.framework.repository.UserRepository;
|
||||
import com.flyfish.framework.service.impl.BaseServiceImpl;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -14,6 +16,9 @@ import java.util.Optional;
|
||||
@Service
|
||||
public class UserService extends BaseServiceImpl<User> {
|
||||
|
||||
@Resource
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
/**
|
||||
* 获取用户数据
|
||||
*
|
||||
@ -24,6 +29,31 @@ public class UserService extends BaseServiceImpl<User> {
|
||||
return ((UserRepository) repository).findByUsername(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User create(User entity) {
|
||||
if (null == entity.getId() && StringUtils.isNotBlank(entity.getPassword())) {
|
||||
entity.setPassword(passwordEncoder.encode(entity.getPassword()));
|
||||
}
|
||||
if (null == entity.getType()) {
|
||||
entity.setType(UserType.ADMIN);
|
||||
}
|
||||
if (null == entity.getEnable()) {
|
||||
entity.setEnable(true);
|
||||
}
|
||||
if (null == entity.getApp()) {
|
||||
entity.setApp(false);
|
||||
}
|
||||
if (null == entity.getCode()) {
|
||||
entity.setCode(entity.getUsername());
|
||||
}
|
||||
return super.create(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User createSelective(User entity) {
|
||||
return create(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> getList(Qo<User> query) {
|
||||
return super.getList(query);
|
||||
|
@ -30,7 +30,7 @@ public class EnumController {
|
||||
private final Map<String, List<EnumValue>> values = new HashMap<>();
|
||||
|
||||
public EnumController() {
|
||||
Reflections reflections = new Reflections("com.flyfish.project");
|
||||
Reflections reflections = new Reflections("com.flyfish.project", "com.flyfish.framework");
|
||||
// 得到Resource注解的类
|
||||
Set<Class<? extends NamedEnum>> classSet = reflections.getSubTypesOf(NamedEnum.class);
|
||||
// 注入
|
||||
|
@ -33,7 +33,8 @@ public abstract class TreeController<T extends TreeDomain<T>, Q extends Qo<T>> e
|
||||
Map<String, List<T>> group = filtered.stream()
|
||||
.collect(Collectors.groupingBy(p -> StringUtils.defaultIfBlank(p.getParentId(), "")));
|
||||
// 第三步,筛选一级树深度
|
||||
List<T> topList = filtered.stream().filter(item -> item.getDepth() == 1).collect(Collectors.toList());
|
||||
List<T> topList = filtered.stream().filter(item -> null != item && TreeDomain.ROOT.equals(item.getParentId()))
|
||||
.collect(Collectors.toList());
|
||||
// 第三步,根据父id的map填充根tree
|
||||
return Result.accept(applyChildren(topList, group));
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.flyfish.framework.handler;
|
||||
|
||||
import com.flyfish.framework.bean.Result;
|
||||
import com.flyfish.framework.domain.po.User;
|
||||
import com.flyfish.framework.service.MongoUserDetailsService;
|
||||
import com.flyfish.framework.transform.DataBufferTransformer;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
@ -12,6 +14,7 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 基于json的登录失败包装,详见Spring Security
|
||||
@ -41,11 +44,19 @@ public class JsonAuthenticationFailureHandler implements ServerAuthenticationFai
|
||||
*/
|
||||
@Override
|
||||
public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException exception) {
|
||||
ServerHttpResponse response = webFilterExchange.getExchange().getResponse();
|
||||
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
return response.writeWith(Mono.fromCallable(() ->
|
||||
dataBufferTransformer.transform(
|
||||
Result.error(descriptionMap.getOrDefault(exception.getClass(), exception.getMessage()))
|
||||
)));
|
||||
return Mono.justOrEmpty(Optional.ofNullable(webFilterExchange.getExchange().getApplicationContext()))
|
||||
.flatMap(applicationContext -> {
|
||||
MongoUserDetailsService userDetailsService = applicationContext.getBean(MongoUserDetailsService.class);
|
||||
Mono<User> mono = exception instanceof BadCredentialsException ? userDetailsService.error(webFilterExchange.getExchange())
|
||||
: Mono.justOrEmpty(Optional.empty());
|
||||
return mono.flatMap(user -> {
|
||||
ServerHttpResponse response = webFilterExchange.getExchange().getResponse();
|
||||
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
return response.writeWith(Mono.fromCallable(() ->
|
||||
dataBufferTransformer.transform(
|
||||
Result.error(descriptionMap.getOrDefault(exception.getClass(), exception.getMessage()))
|
||||
)));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.flyfish.framework.service;
|
||||
|
||||
import com.flyfish.framework.domain.po.User;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
@ -41,4 +42,12 @@ public interface MongoUserDetailsService extends ReactiveUserDetailsService, Rea
|
||||
* @return 结果
|
||||
*/
|
||||
Mono<Void> logout(ServerWebExchange exchange);
|
||||
|
||||
/**
|
||||
* 发生错误时的处理
|
||||
*
|
||||
* @param exchange 交换
|
||||
* @return 结果
|
||||
*/
|
||||
Mono<User> error(ServerWebExchange exchange);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user