调整登录代码逻辑,解决发现的问题

This commit is contained in:
WenG 2021-10-13 00:51:41 +08:00
parent 6eb7f5dd7d
commit c8a662c5fd
22 changed files with 727 additions and 313 deletions

View File

@ -4,12 +4,16 @@ import ink.wgink.pojo.dtos.department.DepartmentSimpleDTO;
import ink.wgink.pojo.dtos.group.GroupSimpleDTO; import ink.wgink.pojo.dtos.group.GroupSimpleDTO;
import ink.wgink.pojo.dtos.position.PositionSimpleDTO; import ink.wgink.pojo.dtos.position.PositionSimpleDTO;
import ink.wgink.pojo.dtos.role.RoleSimpleDTO; import ink.wgink.pojo.dtos.role.RoleSimpleDTO;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList; import java.io.Serializable;
import java.util.Collection; import java.util.*;
import java.util.List; import java.util.function.Function;
/** /**
* @ClassName: UserBO * @ClassName: UserBO
@ -18,7 +22,19 @@ import java.util.List;
* @Date: 2019/2/20 2:22 PM * @Date: 2019/2/20 2:22 PM
* @Version: 1.0 * @Version: 1.0
**/ **/
public class LoginUser extends User { public class LoginUser implements UserDetails, CredentialsContainer {
/**
* org.springframework.security.core.userdetails.user的属性
*/
private static final long serialVersionUID = 1399973719726626183L;
private String password;
private final String username;
private final boolean accountNonExpired;
private final boolean accountNonLocked;
private final boolean credentialsNonExpired;
private Set<GrantedAuthority> authorities;
private final boolean enabled;
private String userId; private String userId;
private String userName; private String userName;
@ -39,16 +55,218 @@ public class LoginUser extends User {
*/ */
private Object expandData; private Object expandData;
public LoginUser() { public LoginUser(String username, String password) {
super("", "", null); this(username, password, true, true, true, true);
} }
public LoginUser(String username, String password, Collection<? extends GrantedAuthority> authorities) { public LoginUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked) {
super(username, password, authorities); if (username != null && !"".equals(username) && password != null) {
this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpired = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
} else {
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
}
} }
public LoginUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { public void setAuthorities(Set<GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); // this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
this.authorities = sortAuthorities(authorities);
}
public Collection<GrantedAuthority> getAuthorities() {
return this.authorities;
}
public String getPassword() {
return this.password;
}
public String getUsername() {
return this.username;
}
public boolean isEnabled() {
return this.enabled;
}
public boolean isAccountNonExpired() {
return this.accountNonExpired;
}
public boolean isAccountNonLocked() {
return this.accountNonLocked;
}
public boolean isCredentialsNonExpired() {
return this.credentialsNonExpired;
}
public void eraseCredentials() {
this.password = null;
}
private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet(new LoginUser.AuthorityComparator());
Iterator iterator = authorities.iterator();
while (iterator.hasNext()) {
GrantedAuthority grantedAuthority = (GrantedAuthority) iterator.next();
sortedAuthorities.add(grantedAuthority);
}
return sortedAuthorities;
}
public boolean equals(Object rhs) {
return rhs instanceof User ? this.username.equals(((LoginUser) rhs).username) : false;
}
public int hashCode() {
return this.username.hashCode();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(": ");
sb.append("Username: ").append(this.username).append("; ");
sb.append("Password: [PROTECTED]; ");
sb.append("Enabled: ").append(this.enabled).append("; ");
sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; ");
sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
if (!this.authorities.isEmpty()) {
sb.append("Granted Authorities: ");
boolean first = true;
Iterator var3 = this.authorities.iterator();
while (var3.hasNext()) {
GrantedAuthority auth = (GrantedAuthority) var3.next();
if (!first) {
sb.append(",");
}
first = false;
sb.append(auth);
}
} else {
sb.append("Not granted any authorities");
}
return sb.toString();
}
public static LoginUser.UserBuilder withUsername(String username) {
return builder().username(username);
}
public static LoginUser.UserBuilder builder() {
return new LoginUser.UserBuilder();
}
public static LoginUser.UserBuilder withUserDetails(UserDetails userDetails) {
return withUsername(userDetails.getUsername()).password(userDetails.getPassword()).accountExpired(!userDetails.isAccountNonExpired()).accountLocked(!userDetails.isAccountNonLocked()).authorities(userDetails.getAuthorities()).credentialsExpired(!userDetails.isCredentialsNonExpired()).disabled(!userDetails.isEnabled());
}
public static class UserBuilder {
private String username;
private String password;
private List<GrantedAuthority> authorities;
private boolean accountExpired;
private boolean accountLocked;
private boolean credentialsExpired;
private boolean disabled;
private Function<String, String> passwordEncoder;
private UserBuilder() {
this.passwordEncoder = (password) -> {
return password;
};
}
public LoginUser.UserBuilder username(String username) {
this.username = username;
return this;
}
public LoginUser.UserBuilder password(String password) {
this.password = password;
return this;
}
public LoginUser.UserBuilder passwordEncoder(Function<String, String> encoder) {
this.passwordEncoder = encoder;
return this;
}
public LoginUser.UserBuilder roles(String... roles) {
List<GrantedAuthority> authorities = new ArrayList(roles.length);
String[] var3 = roles;
int var4 = roles.length;
for (int var5 = 0; var5 < var4; ++var5) {
String role = var3[var5];
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
}
return this.authorities((Collection) authorities);
}
public LoginUser.UserBuilder authorities(GrantedAuthority... authorities) {
return this.authorities((Collection) Arrays.asList(authorities));
}
public LoginUser.UserBuilder authorities(Collection<? extends GrantedAuthority> authorities) {
this.authorities = new ArrayList(authorities);
return this;
}
public LoginUser.UserBuilder authorities(String... authorities) {
return this.authorities((Collection) AuthorityUtils.createAuthorityList(authorities));
}
public LoginUser.UserBuilder accountExpired(boolean accountExpired) {
this.accountExpired = accountExpired;
return this;
}
public LoginUser.UserBuilder accountLocked(boolean accountLocked) {
this.accountLocked = accountLocked;
return this;
}
public LoginUser.UserBuilder credentialsExpired(boolean credentialsExpired) {
this.credentialsExpired = credentialsExpired;
return this;
}
public LoginUser.UserBuilder disabled(boolean disabled) {
this.disabled = disabled;
return this;
}
public UserDetails build() {
String encodedPassword = (String) this.passwordEncoder.apply(this.password);
return new User(this.username, encodedPassword, !this.disabled, !this.accountExpired, !this.credentialsExpired, !this.accountLocked, this.authorities);
}
}
private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
private static final long serialVersionUID = 510L;
private AuthorityComparator() {
}
public int compare(GrantedAuthority g1, GrantedAuthority g2) {
if (g2.getAuthority() == null) {
return -1;
} else {
return g1.getAuthority() == null ? 1 : g1.getAuthority().compareTo(g2.getAuthority());
}
}
} }
public String getUserId() { public String getUserId() {
@ -171,4 +389,5 @@ public class LoginUser extends User {
public void setExpandData(Object expandData) { public void setExpandData(Object expandData) {
this.expandData = expandData; this.expandData = expandData;
} }
} }

View File

@ -1,17 +1,44 @@
package ink.wgink.login.base.authentication.user; package ink.wgink.login.base.authentication.user;
import ink.wgink.interfaces.consts.ISystemConstant; import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
import ink.wgink.interfaces.group.IGroupUserBaseService;
import ink.wgink.interfaces.position.IPositionUserBaseService;
import ink.wgink.interfaces.role.IRoleMenuBaseService;
import ink.wgink.interfaces.role.IRolePermissionBaseService;
import ink.wgink.interfaces.role.IRoleUserBaseService;
import ink.wgink.login.base.consts.IUserCenterConst;
import ink.wgink.login.base.enums.LoginTypeEnum; import ink.wgink.login.base.enums.LoginTypeEnum;
import ink.wgink.login.base.exceptions.UserAuthenticationException; import ink.wgink.login.base.exceptions.UserAuthenticationException;
import ink.wgink.login.base.service.user.UserLoginService; import ink.wgink.login.base.service.user.UserLoginService;
import ink.wgink.pojo.bos.LoginUser; import ink.wgink.pojo.bos.LoginUser;
import ink.wgink.pojo.bos.RoleGrantedAuthorityBO;
import ink.wgink.pojo.dtos.department.DepartmentSimpleDTO;
import ink.wgink.pojo.dtos.group.GroupSimpleDTO;
import ink.wgink.pojo.dtos.position.PositionSimpleDTO;
import ink.wgink.pojo.dtos.role.RoleSimpleDTO;
import ink.wgink.pojo.pos.DepartmentPO;
import ink.wgink.pojo.pos.GroupPO;
import ink.wgink.pojo.pos.PositionPO;
import ink.wgink.pojo.pos.RolePO;
import ink.wgink.properties.AccessControlProperties;
import ink.wgink.service.department.service.IDepartmentUserService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/** /**
* When you feel like quitting. Think about why you started * When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始 * 当你想要放弃的时候想想当初你为何开始
@ -23,27 +50,158 @@ import org.springframework.security.crypto.password.PasswordEncoder;
* @Version: 1.0 * @Version: 1.0
**/ **/
public class UserAuthenticationProvider implements AuthenticationProvider { public class UserAuthenticationProvider implements AuthenticationProvider {
private static final Logger LOG = LoggerFactory.getLogger(UserAuthenticationProvider.class);
private UserDetailsService userDetailsService; private UserDetailsService userDetailsService;
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
private UserLoginService userLoginService; private UserLoginService userLoginService;
private IRoleUserBaseService roleUserBaseService;
private IRoleMenuBaseService roleMenuBaseService;
private IRolePermissionBaseService rolePermissionService;
private IGroupUserBaseService groupUserBaseService;
private IPositionUserBaseService positionUserBaseService;
private ILoginHandlerService loginHandler;
private IDepartmentUserService departmentUserService;
private AccessControlProperties accessControlProperties;
private HttpSession httpSession;
@Override @Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException { public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UserAuthenticationToken userAuthenticationToken = (UserAuthenticationToken) authentication; UserAuthenticationToken userAuthenticationToken = (UserAuthenticationToken) authentication;
LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(userAuthenticationToken.getPrincipal().toString()); String username = userAuthenticationToken.getPrincipal().toString();
httpSession.setAttribute(IUserCenterConst.LOGIN_USERNAME, username);
LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(username);
if (!passwordEncoder.matches(userAuthenticationToken.getCredentials().toString(), loginUser.getPassword())) { if (!passwordEncoder.matches(userAuthenticationToken.getCredentials().toString(), loginUser.getPassword())) {
throw new UserAuthenticationException("用户名或密码错误"); throw new UserAuthenticationException("用户名或密码错误");
} }
// 清空session中的错误信息
httpSession.removeAttribute(IUserCenterConst.ERROR_MESSAGE);
httpSession.removeAttribute(IUserCenterConst.LOGIN_USERNAME);
LOG.debug("设置权限权限");
Set<GrantedAuthority> grantedAuthorities = new LinkedHashSet<>();
if (StringUtils.equalsIgnoreCase(ISystemConstant.ADMIN, loginUser.getUsername())) {
grantedAuthorities.add(new RoleGrantedAuthorityBO(ISystemConstant.ADMIN));
} else {
List<RolePO> rolePOs = null;
// 先处理授权再创建对象否则 grantedAuthorities 中无法赋值
if (roleUserBaseService != null) {
LOG.debug("设置角色信息");
rolePOs = roleUserBaseService.listRolePOByUserId(loginUser.getUserId());
removalDuplicateRole(rolePOs);
grantedAuthorities.addAll(loadRoleAuthority(rolePOs));
if (grantedAuthorities.isEmpty()) {
throw new UserAuthenticationException(loginUser.getUsername() + "用户无任何角色");
}
}
if (rolePOs != null) {
List<RoleSimpleDTO> roleSimpleDTOs = roleUserBaseService.listSimple(rolePOs);
loginUser.setRoles(roleSimpleDTOs);
}
LOG.debug("设置部门状态");
List<DepartmentPO> departmentPOs = departmentUserService.listDepartmentPOByUserId(loginUser.getUserId());
List<DepartmentSimpleDTO> departmentSimpleDTOs = departmentUserService.listSimple(departmentPOs);
loginUser.setDepartments(departmentSimpleDTOs);
if (groupUserBaseService != null) {
LOG.debug("设置组信息");
List<GroupPO> groupPOs = groupUserBaseService.listGroupPOByUserId(loginUser.getUserId());
List<GroupSimpleDTO> groupSimpleDTOs = groupUserBaseService.listSimple(groupPOs);
loginUser.setGroups(groupSimpleDTOs);
}
if (positionUserBaseService != null) {
LOG.debug("设置职位");
List<PositionPO> positionPOs = positionUserBaseService.listPositionPOByUserId(loginUser.getUserId());
List<PositionSimpleDTO> positionSimpleDTOs = positionUserBaseService.listSimple(positionPOs);
loginUser.setPositions(positionSimpleDTOs);
}
}
// 设置权限
loginUser.setAuthorities(grantedAuthorities);
loginHandler(loginUser);
// 设置数据权限
if (!StringUtils.equalsIgnoreCase(ISystemConstant.ADMIN, loginUser.getUsername())) { if (!StringUtils.equalsIgnoreCase(ISystemConstant.ADMIN, loginUser.getUsername())) {
userLoginService.setUserDataAuthority(loginUser); userLoginService.setUserDataAuthority(loginUser);
} }
// 更新登录信息
userLoginService.updateUserLoginInfo(loginUser.getUserId(), loginUser.getUserName(), LoginTypeEnum.USERNAME_AND_PASSWORD.getValue()); userLoginService.updateUserLoginInfo(loginUser.getUserId(), loginUser.getUserName(), LoginTypeEnum.USERNAME_AND_PASSWORD.getValue());
UserAuthenticationToken userAuthenticationTokenResult = new UserAuthenticationToken(loginUser, null, loginUser.getAuthorities()); UserAuthenticationToken userAuthenticationTokenResult = new UserAuthenticationToken(loginUser, null, loginUser.getAuthorities());
userAuthenticationTokenResult.setDetails(userAuthenticationToken.getDetails()); userAuthenticationTokenResult.setDetails(userAuthenticationToken.getDetails());
return userAuthenticationTokenResult; return userAuthenticationTokenResult;
} }
/**
* 登录处理
*
* @param loginUser
*/
private void loginHandler(LoginUser loginUser) {
if (loginHandler != null) {
try {
loginHandler.handle(loginUser);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new UserAuthenticationException("登录异常");
}
}
}
/**
* 角色授权列表
*
* @param rolePOs
* @return
*/
private List<GrantedAuthority> loadRoleAuthority(List<RolePO> rolePOs) {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
if (null != rolePOs && !rolePOs.isEmpty()) {
// 设置菜单权限
rolePOs.forEach((rolePO) -> {
List<String> menuUrls = roleMenuBaseService.listMenuUrl(rolePO.getRoleId());
List<String> inserts = new ArrayList<>();
List<String> deletes = new ArrayList<>();
List<String> updates = new ArrayList<>();
List<String> queries = new ArrayList<>();
if (accessControlProperties.getRolePermission()) {
inserts.addAll(rolePermissionService.listPermissionUrl(rolePO.getRoleId(), IRolePermissionBaseService.PERMISSION_INSERT));
deletes.addAll(rolePermissionService.listPermissionUrl(rolePO.getRoleId(), IRolePermissionBaseService.PERMISSION_DELETE));
updates.addAll(rolePermissionService.listPermissionUrl(rolePO.getRoleId(), IRolePermissionBaseService.PERMISSION_UPDATE));
queries.addAll(rolePermissionService.listPermissionUrl(rolePO.getRoleId(), IRolePermissionBaseService.PERMISSION_QUERY));
}
grantedAuthorities.add(new RoleGrantedAuthorityBO(rolePO.getRoleId(), rolePO.getRoleName(), menuUrls, inserts, deletes, updates, queries));
});
}
return grantedAuthorities;
}
/**
* 删除重复的角色
*
* @param rolePOs
*/
private void removalDuplicateRole(List<RolePO> rolePOs) {
if (rolePOs == null || rolePOs.isEmpty()) {
return;
}
for (int i = 0; i < rolePOs.size(); i++) {
RolePO rolePO = rolePOs.get(i);
boolean isExist = false;
for (int j = i + 1; j < rolePOs.size(); j++) {
if (StringUtils.equals(rolePO.getRoleId(), rolePOs.get(j).getRoleId())) {
isExist = true;
break;
}
}
if (isExist) {
rolePOs.remove(i);
i--;
break;
}
}
}
@Override @Override
public boolean supports(Class<?> authentication) { public boolean supports(Class<?> authentication) {
return UserAuthenticationToken.class.isAssignableFrom(authentication); return UserAuthenticationToken.class.isAssignableFrom(authentication);
@ -60,4 +218,40 @@ public class UserAuthenticationProvider implements AuthenticationProvider {
public void setUserLoginService(UserLoginService userLoginService) { public void setUserLoginService(UserLoginService userLoginService) {
this.userLoginService = userLoginService; this.userLoginService = userLoginService;
} }
public void setRoleUserBaseService(IRoleUserBaseService roleUserBaseService) {
this.roleUserBaseService = roleUserBaseService;
}
public void setRoleMenuBaseService(IRoleMenuBaseService roleMenuBaseService) {
this.roleMenuBaseService = roleMenuBaseService;
}
public void setRolePermissionService(IRolePermissionBaseService rolePermissionService) {
this.rolePermissionService = rolePermissionService;
}
public void setGroupUserBaseService(IGroupUserBaseService groupUserBaseService) {
this.groupUserBaseService = groupUserBaseService;
}
public void setPositionUserBaseService(IPositionUserBaseService positionUserBaseService) {
this.positionUserBaseService = positionUserBaseService;
}
public void setLoginHandler(ILoginHandlerService loginHandler) {
this.loginHandler = loginHandler;
}
public void setDepartmentUserService(IDepartmentUserService departmentUserService) {
this.departmentUserService = departmentUserService;
}
public void setAccessControlProperties(AccessControlProperties accessControlProperties) {
this.accessControlProperties = accessControlProperties;
}
public void setHttpSession(HttpSession httpSession) {
this.httpSession = httpSession;
}
} }

View File

@ -13,6 +13,7 @@ package ink.wgink.login.base.consts;
public interface IUserCenterConst { public interface IUserCenterConst {
String ERROR = "error"; String ERROR = "error";
String LOGIN_USERNAME = "loginUsername";
/** /**
* 错误信息 * 错误信息
*/ */

View File

@ -1,12 +1,20 @@
package ink.wgink.login.base.security; package ink.wgink.login.base.security;
import ink.wgink.common.handler.AccessDenyHandler; import ink.wgink.common.handler.AccessDenyHandler;
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
import ink.wgink.interfaces.group.IGroupUserBaseService;
import ink.wgink.interfaces.position.IPositionUserBaseService;
import ink.wgink.interfaces.role.IRoleMenuBaseService;
import ink.wgink.interfaces.role.IRolePermissionBaseService;
import ink.wgink.interfaces.role.IRoleUserBaseService;
import ink.wgink.login.base.handler.LoginFailureHandler; import ink.wgink.login.base.handler.LoginFailureHandler;
import ink.wgink.login.base.handler.LogoutHandler; import ink.wgink.login.base.handler.LogoutHandler;
import ink.wgink.login.base.security.user.UserSecurityConfig; import ink.wgink.login.base.security.user.UserSecurityConfig;
import ink.wgink.login.base.service.user.UserDetailServiceImpl; import ink.wgink.login.base.service.user.UserDetailServiceImpl;
import ink.wgink.login.base.service.user.UserLoginService; import ink.wgink.login.base.service.user.UserLoginService;
import ink.wgink.properties.AccessControlProperties;
import ink.wgink.properties.BaseProperties; import ink.wgink.properties.BaseProperties;
import ink.wgink.service.department.service.IDepartmentUserService;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -18,6 +26,8 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import javax.servlet.http.HttpSession;
/** /**
* @ClassName: WebSecurityConfig * @ClassName: WebSecurityConfig
* @Description: security配置 * @Description: security配置
@ -34,6 +44,24 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private UserDetailServiceImpl userDetailService; private UserDetailServiceImpl userDetailService;
@Autowired @Autowired
private UserLoginService userLoginService; private UserLoginService userLoginService;
@Autowired(required = false)
private IRoleUserBaseService roleUserBaseService;
@Autowired(required = false)
private IRoleMenuBaseService roleMenuBaseService;
@Autowired(required = false)
private IRolePermissionBaseService rolePermissionService;
@Autowired(required = false)
private IGroupUserBaseService groupUserBaseService;
@Autowired(required = false)
private IPositionUserBaseService positionUserBaseService;
@Autowired(required = false)
private ILoginHandlerService loginHandler;
@Autowired
private IDepartmentUserService departmentUserService;
@Autowired
private AccessControlProperties accessControlProperties;
@Autowired
private HttpSession httpSession;
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
@ -107,6 +135,15 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
userSecurityConfig.setLoginProcessUrl(baseProperties.getLoginProcess()); userSecurityConfig.setLoginProcessUrl(baseProperties.getLoginProcess());
userSecurityConfig.setLoginFailureHandler(loginFailureHandler); userSecurityConfig.setLoginFailureHandler(loginFailureHandler);
userSecurityConfig.setUserLoginService(userLoginService); userSecurityConfig.setUserLoginService(userLoginService);
userSecurityConfig.setRoleUserBaseService(roleUserBaseService);
userSecurityConfig.setRoleMenuBaseService(roleMenuBaseService);
userSecurityConfig.setRolePermissionService(rolePermissionService);
userSecurityConfig.setGroupUserBaseService(groupUserBaseService);
userSecurityConfig.setPositionUserBaseService(positionUserBaseService);
userSecurityConfig.setLoginHandler(loginHandler);
userSecurityConfig.setDepartmentUserService(departmentUserService);
userSecurityConfig.setAccessControlProperties(accessControlProperties);
userSecurityConfig.setHttpSession(httpSession);
http.apply(userSecurityConfig); http.apply(userSecurityConfig);
} }

View File

@ -1,10 +1,18 @@
package ink.wgink.login.base.security.user; package ink.wgink.login.base.security.user;
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
import ink.wgink.interfaces.group.IGroupUserBaseService;
import ink.wgink.interfaces.position.IPositionUserBaseService;
import ink.wgink.interfaces.role.IRoleMenuBaseService;
import ink.wgink.interfaces.role.IRolePermissionBaseService;
import ink.wgink.interfaces.role.IRoleUserBaseService;
import ink.wgink.login.base.authentication.user.UserAuthenticationFilter; import ink.wgink.login.base.authentication.user.UserAuthenticationFilter;
import ink.wgink.login.base.authentication.user.UserAuthenticationProvider; import ink.wgink.login.base.authentication.user.UserAuthenticationProvider;
import ink.wgink.login.base.handler.LoginFailureHandler; import ink.wgink.login.base.handler.LoginFailureHandler;
import ink.wgink.login.base.service.user.UserDetailServiceImpl; import ink.wgink.login.base.service.user.UserDetailServiceImpl;
import ink.wgink.login.base.service.user.UserLoginService; import ink.wgink.login.base.service.user.UserLoginService;
import ink.wgink.properties.AccessControlProperties;
import ink.wgink.service.department.service.IDepartmentUserService;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@ -12,6 +20,8 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpSession;
/** /**
* When you feel like quitting. Think about why you started * When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始 * 当你想要放弃的时候想想当初你为何开始
@ -29,6 +39,15 @@ public class UserSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurit
private String loginProcessUrl; private String loginProcessUrl;
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
private UserLoginService userLoginService; private UserLoginService userLoginService;
private IRoleUserBaseService roleUserBaseService;
private IRoleMenuBaseService roleMenuBaseService;
private IRolePermissionBaseService rolePermissionService;
private IGroupUserBaseService groupUserBaseService;
private IPositionUserBaseService positionUserBaseService;
private ILoginHandlerService loginHandler;
private IDepartmentUserService departmentUserService;
private AccessControlProperties accessControlProperties;
private HttpSession httpSession;
@Override @Override
public void configure(HttpSecurity http) throws Exception { public void configure(HttpSecurity http) throws Exception {
@ -42,6 +61,15 @@ public class UserSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurit
userAuthenticationProvider.setPasswordEncoder(passwordEncoder); userAuthenticationProvider.setPasswordEncoder(passwordEncoder);
userAuthenticationProvider.setUserDetailsService(userDetailService); userAuthenticationProvider.setUserDetailsService(userDetailService);
userAuthenticationProvider.setUserLoginService(userLoginService); userAuthenticationProvider.setUserLoginService(userLoginService);
userAuthenticationProvider.setRoleUserBaseService(roleUserBaseService);
userAuthenticationProvider.setRoleMenuBaseService(roleMenuBaseService);
userAuthenticationProvider.setRolePermissionService(rolePermissionService);
userAuthenticationProvider.setGroupUserBaseService(groupUserBaseService);
userAuthenticationProvider.setPositionUserBaseService(positionUserBaseService);
userAuthenticationProvider.setLoginHandler(loginHandler);
userAuthenticationProvider.setDepartmentUserService(departmentUserService);
userAuthenticationProvider.setAccessControlProperties(accessControlProperties);
userAuthenticationProvider.setHttpSession(httpSession);
// 加入SpringSecurity的authentication管理的provider集合当中并且添加到UsernamePasswordAuthenticationFilter之前 // 加入SpringSecurity的authentication管理的provider集合当中并且添加到UsernamePasswordAuthenticationFilter之前
http.authenticationProvider(userAuthenticationProvider).addFilterBefore(userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); http.authenticationProvider(userAuthenticationProvider).addFilterBefore(userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
} }
@ -65,4 +93,40 @@ public class UserSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurit
public void setUserLoginService(UserLoginService userLoginService) { public void setUserLoginService(UserLoginService userLoginService) {
this.userLoginService = userLoginService; this.userLoginService = userLoginService;
} }
public void setRoleUserBaseService(IRoleUserBaseService roleUserBaseService) {
this.roleUserBaseService = roleUserBaseService;
}
public void setRoleMenuBaseService(IRoleMenuBaseService roleMenuBaseService) {
this.roleMenuBaseService = roleMenuBaseService;
}
public void setRolePermissionService(IRolePermissionBaseService rolePermissionService) {
this.rolePermissionService = rolePermissionService;
}
public void setGroupUserBaseService(IGroupUserBaseService groupUserBaseService) {
this.groupUserBaseService = groupUserBaseService;
}
public void setPositionUserBaseService(IPositionUserBaseService positionUserBaseService) {
this.positionUserBaseService = positionUserBaseService;
}
public void setLoginHandler(ILoginHandlerService loginHandler) {
this.loginHandler = loginHandler;
}
public void setDepartmentUserService(IDepartmentUserService departmentUserService) {
this.departmentUserService = departmentUserService;
}
public void setAccessControlProperties(AccessControlProperties accessControlProperties) {
this.accessControlProperties = accessControlProperties;
}
public void setHttpSession(HttpSession httpSession) {
this.httpSession = httpSession;
}
} }

View File

@ -33,6 +33,7 @@ public class OAuthServiceImpl implements IOAuthService {
Map<String, Object> config = ConfigManager.getInstance().getConfig(); Map<String, Object> config = ConfigManager.getInstance().getConfig();
Map<String, Object> pageParams = new HashMap<>(16); Map<String, Object> pageParams = new HashMap<>(16);
pageParams.put(IUserCenterConst.ERROR_MESSAGE, request.getSession().getAttribute(IUserCenterConst.ERROR_MESSAGE)); pageParams.put(IUserCenterConst.ERROR_MESSAGE, request.getSession().getAttribute(IUserCenterConst.ERROR_MESSAGE));
pageParams.put(IUserCenterConst.LOGIN_USERNAME, request.getSession().getAttribute(IUserCenterConst.LOGIN_USERNAME));
// 服务地址 // 服务地址
pageParams.put(IUserCenterConst.SERVER_URL, serverProperties.getUrl()); pageParams.put(IUserCenterConst.SERVER_URL, serverProperties.getUrl());
// 系统LOGO // 系统LOGO

View File

@ -46,6 +46,7 @@ public class LoginFormServiceImpl extends DefaultBaseService implements ILoginFo
public void remove(List<String> loginFormIds) { public void remove(List<String> loginFormIds) {
Map<String, Object> params = getHashMap(2); Map<String, Object> params = getHashMap(2);
params.put("loginFormIds", loginFormIds); params.put("loginFormIds", loginFormIds);
setUpdateInfo(params);
loginFormDao.remove(params); loginFormDao.remove(params);
} }

View File

@ -2,44 +2,22 @@ package ink.wgink.login.base.service.user;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import ink.wgink.interfaces.consts.ISystemConstant; import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
import ink.wgink.interfaces.group.IGroupUserBaseService;
import ink.wgink.interfaces.position.IPositionUserBaseService;
import ink.wgink.interfaces.role.IRoleMenuBaseService;
import ink.wgink.interfaces.role.IRolePermissionBaseService;
import ink.wgink.interfaces.role.IRoleUserBaseService;
import ink.wgink.interfaces.user.IUserDetailCheckService; import ink.wgink.interfaces.user.IUserDetailCheckService;
import ink.wgink.login.base.consts.IUserCenterConst;
import ink.wgink.login.base.exceptions.UserAuthenticationException; import ink.wgink.login.base.exceptions.UserAuthenticationException;
import ink.wgink.login.base.manager.ConfigManager; import ink.wgink.login.base.manager.ConfigManager;
import ink.wgink.pojo.bos.LoginUser; import ink.wgink.pojo.bos.LoginUser;
import ink.wgink.pojo.bos.RoleGrantedAuthorityBO;
import ink.wgink.pojo.dtos.department.DepartmentSimpleDTO;
import ink.wgink.pojo.dtos.group.GroupSimpleDTO;
import ink.wgink.pojo.dtos.position.PositionSimpleDTO;
import ink.wgink.pojo.dtos.role.RoleSimpleDTO;
import ink.wgink.pojo.pos.DepartmentPO;
import ink.wgink.pojo.pos.GroupPO;
import ink.wgink.pojo.pos.PositionPO;
import ink.wgink.pojo.pos.RolePO;
import ink.wgink.properties.AccessControlProperties;
import ink.wgink.service.department.service.IDepartmentUserService;
import ink.wgink.service.user.pojo.pos.UserPO; import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.service.IUserService; import ink.wgink.service.user.service.IUserService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession; import java.util.Map;
import java.util.*;
/** /**
* @ClassName: UserDetailServiceImpl * @ClassName: UserDetailServiceImpl
@ -51,28 +29,8 @@ import java.util.*;
@Service @Service
public class UserDetailServiceImpl implements UserDetailsService, IUserDetailCheckService { public class UserDetailServiceImpl implements UserDetailsService, IUserDetailCheckService {
private static final Logger LOG = LoggerFactory.getLogger(UserDetailServiceImpl.class);
@Autowired(required = false)
private IRoleUserBaseService roleUserBaseService;
@Autowired(required = false)
private IRoleMenuBaseService roleMenuBaseService;
@Autowired(required = false)
private IRolePermissionBaseService rolePermissionService;
@Autowired(required = false)
private IGroupUserBaseService groupUserBaseService;
@Autowired(required = false)
private IPositionUserBaseService positionUserBaseService;
@Autowired(required = false)
private ILoginHandlerService loginHandler;
@Autowired
private IDepartmentUserService departmentUserService;
@Autowired @Autowired
private IUserService userService; private IUserService userService;
@Autowired
private AccessControlProperties accessControlProperties;
@Autowired
private HttpSession httpSession;
public UserDetailServiceImpl() { public UserDetailServiceImpl() {
super(); super();
@ -95,85 +53,24 @@ public class UserDetailServiceImpl implements UserDetailsService, IUserDetailChe
if (userPO.getUserState() == 1) { if (userPO.getUserState() == 1) {
throw new UserAuthenticationException("账号已冻结"); throw new UserAuthenticationException("账号已冻结");
} }
if (isAccountExpired(userPO)) {
LOG.debug("设置权限权限"); throw new UserAuthenticationException("账号已经过期");
LoginUser loginUser;
Set<GrantedAuthority> grantedAuthorities = new LinkedHashSet<>();
if (StringUtils.equalsIgnoreCase(ISystemConstant.ADMIN, username)) {
grantedAuthorities.add(new RoleGrantedAuthorityBO(ISystemConstant.ADMIN));
loginUser = createUserBO(userPO, grantedAuthorities);
} else {
List<RolePO> rolePOs = null;
// 先处理授权再创建对象否则 grantedAuthorities 中无法赋值
if (roleUserBaseService != null) {
LOG.debug("设置角色信息");
rolePOs = roleUserBaseService.listRolePOByUserId(userPO.getUserId());
removalDuplicateRole(rolePOs);
grantedAuthorities.addAll(loadRoleAuthority(rolePOs));
if (grantedAuthorities.isEmpty()) {
throw new UserAuthenticationException(username + "用户无任何角色");
}
}
loginUser = createUserBO(userPO, grantedAuthorities);
if (rolePOs != null) {
List<RoleSimpleDTO> roleSimpleDTOs = roleUserBaseService.listSimple(rolePOs);
loginUser.setRoles(roleSimpleDTOs);
}
LOG.debug("设置部门状态");
List<DepartmentPO> departmentPOs = departmentUserService.listDepartmentPOByUserId(userPO.getUserId());
List<DepartmentSimpleDTO> departmentSimpleDTOs = departmentUserService.listSimple(departmentPOs);
loginUser.setDepartments(departmentSimpleDTOs);
if (groupUserBaseService != null) {
LOG.debug("设置组信息");
List<GroupPO> groupPOs = groupUserBaseService.listGroupPOByUserId(userPO.getUserId());
List<GroupSimpleDTO> groupSimpleDTOs = groupUserBaseService.listSimple(groupPOs);
loginUser.setGroups(groupSimpleDTOs);
}
if (positionUserBaseService != null) {
LOG.debug("设置职位");
List<PositionPO> positionPOs = positionUserBaseService.listPositionPOByUserId(userPO.getUserId());
List<PositionSimpleDTO> positionSimpleDTOs = positionUserBaseService.listSimple(positionPOs);
loginUser.setPositions(positionSimpleDTOs);
}
}
loginHandler(loginUser);
// 清空session中的错误信息
httpSession.removeAttribute(IUserCenterConst.ERROR_MESSAGE);
return loginUser;
}
/**
* 登录处理
*
* @param loginUser
*/
private void loginHandler(LoginUser loginUser) {
if (loginHandler != null) {
try {
loginHandler.handle(loginUser);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new UserAuthenticationException("登录异常");
}
} }
return createUserBO(userPO);
} }
/** /**
* 创建UserBO * 创建UserBO
* *
* @param userPO * @param userPO
* @param grantedAuthorities
* @return * @return
*/ */
private LoginUser createUserBO(UserPO userPO, Set<GrantedAuthority> grantedAuthorities) { private LoginUser createUserBO(UserPO userPO) {
LoginUser loginUser = new LoginUser(userPO.getUserUsername(), userPO.getUserPassword(), LoginUser loginUser = new LoginUser(userPO.getUserUsername(), userPO.getUserPassword(),
userPO.getUserType() == 1 ? true : false, userPO.getUserType() == 1 ? true : false,
isAccountNonExpired(userPO), isAccountNonExpired(userPO),
isCredentialsNonExpired(userPO), isCredentialsNonExpired(userPO),
userPO.getUserState() == 0 ? true : false, grantedAuthorities); userPO.getUserState() == 0 ? true : false);
loginUser.setUserId(userPO.getUserId()); loginUser.setUserId(userPO.getUserId());
loginUser.setUserName(userPO.getUserName()); loginUser.setUserName(userPO.getUserName());
loginUser.setUserPhone(userPO.getUserPhone()); loginUser.setUserPhone(userPO.getUserPhone());
@ -235,58 +132,21 @@ public class UserDetailServiceImpl implements UserDetailsService, IUserDetailChe
} }
/** /**
* 角色授权列表 * 账号是否过期
* *
* @param rolePOs * @param userPO
* @return * @return
*/ */
private List<GrantedAuthority> loadRoleAuthority(List<RolePO> rolePOs) { private boolean isAccountExpired(UserPO userPO) {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); if (StringUtils.isBlank(userPO.getUserExpiredDate())) {
if (null != rolePOs && !rolePOs.isEmpty()) { return false;
// 设置菜单权限
rolePOs.forEach((rolePO) -> {
List<String> menuUrls = roleMenuBaseService.listMenuUrl(rolePO.getRoleId());
List<String> inserts = new ArrayList<>();
List<String> deletes = new ArrayList<>();
List<String> updates = new ArrayList<>();
List<String> queries = new ArrayList<>();
if (accessControlProperties.getRolePermission()) {
inserts.addAll(rolePermissionService.listPermissionUrl(rolePO.getRoleId(), IRolePermissionBaseService.PERMISSION_INSERT));
deletes.addAll(rolePermissionService.listPermissionUrl(rolePO.getRoleId(), IRolePermissionBaseService.PERMISSION_DELETE));
updates.addAll(rolePermissionService.listPermissionUrl(rolePO.getRoleId(), IRolePermissionBaseService.PERMISSION_UPDATE));
queries.addAll(rolePermissionService.listPermissionUrl(rolePO.getRoleId(), IRolePermissionBaseService.PERMISSION_QUERY));
}
grantedAuthorities.add(new RoleGrantedAuthorityBO(rolePO.getRoleId(), rolePO.getRoleName(), menuUrls, inserts, deletes, updates, queries));
});
}
return grantedAuthorities;
}
/**
* 删除重复的角色
*
* @param rolePOs
*/
private void removalDuplicateRole(List<RolePO> rolePOs) {
if (rolePOs == null || rolePOs.isEmpty()) {
return;
}
for (int i = 0; i < rolePOs.size(); i++) {
RolePO rolePO = rolePOs.get(i);
boolean isExist = false;
for (int j = i + 1; j < rolePOs.size(); j++) {
if (StringUtils.equals(rolePO.getRoleId(), rolePOs.get(j).getRoleId())) {
isExist = true;
break;
}
}
if (isExist) {
rolePOs.remove(i);
i--;
break;
} }
DateTime now = DateTime.now();
DateTime expiredDateTime = DateTime.parse(userPO.getUserExpiredDate(), DateTimeFormat.forPattern(ISystemConstant.DATE_FORMATTER_YYYY_MM_DD_HH_MM_SS));
if (expiredDateTime.isAfter(now)) {
return false;
} }
return true;
} }
} }

View File

@ -162,6 +162,12 @@
gmt_create gmt_create
FROM FROM
sys_login_form sys_login_form
WHERE
is_delete = 0
<if test="keywords != null and keywords != ''">
AND
name LIKE CONCAT('%', #{keywords}, '%')
</if>
</select> </select>
<!-- 登录form表单详情 --> <!-- 登录form表单详情 -->
@ -182,10 +188,13 @@
FROM FROM
sys_login_form sys_login_form
WHERE WHERE
is_delete = 0
<if test="loginFormId != null and loginFormId != ''"> <if test="loginFormId != null and loginFormId != ''">
AND
loginform_id = #{loginFormId} loginform_id = #{loginFormId}
</if> </if>
<if test="isActive != null"> <if test="isActive != null">
AND
is_active = #{isActive} is_active = #{isActive}
</if> </if>
</select> </select>

View File

@ -104,13 +104,14 @@
var md5 = layui.md5; var md5 = layui.md5;
var base64 = layui.base64; var base64 = layui.base64;
var pageParams = [[${pageParams}]];
new Vue({ new Vue({
el: '#app', el: '#app',
data: { data: {
pageParams: [[${pageParams}]], pageParams: pageParams,
formData: { formData: {
verificationCode: '', verificationCode: '',
username: '', username: pageParams.loginUsername,
password: '', password: '',
remember: false remember: false
} }

View File

@ -28,6 +28,16 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item">
<label class="layui-form-label">编号</label>
<div class="layui-input-block">
<input id="departmentNo" type="text" name="departmentNo" placeholder="请输入组织编号" class="layui-input" maxlength="255">
</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12"> <div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">名称(英文)</label> <label class="layui-form-label">名称(英文)</label>
@ -36,8 +46,6 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12"> <div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">名称(其他)</label> <label class="layui-form-label">名称(其他)</label>
@ -46,6 +54,8 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12"> <div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">组织类型 *</label> <label class="layui-form-label">组织类型 *</label>

View File

@ -34,6 +34,16 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item">
<label class="layui-form-label">编号</label>
<div class="layui-input-block">
<input id="departmentNo" type="text" name="departmentNo" placeholder="请输入组织编号" class="layui-input" maxlength="255">
</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12"> <div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">名称(英文)</label> <label class="layui-form-label">名称(英文)</label>
@ -42,8 +52,6 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12"> <div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">名称(其他)</label> <label class="layui-form-label">名称(其他)</label>
@ -52,6 +60,8 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12"> <div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">组织类型 *</label> <label class="layui-form-label">组织类型 *</label>

View File

@ -65,7 +65,7 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">编号</label> <label class="layui-form-label">编号</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input id="departmentNo" type="text" name="departmentNo" lay-verify="required" placeholder="请输入组织编号" class="layui-input" maxlength="50"> <input id="departmentNo" type="text" name="departmentNo" placeholder="请输入组织编号" class="layui-input" maxlength="255">
</div> </div>
</div> </div>
</div> </div>

View File

@ -65,7 +65,7 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">编号</label> <label class="layui-form-label">编号</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input id="departmentNo" type="text" name="departmentNo" lay-verify="required" placeholder="请输入组织编号" class="layui-input" maxlength="50"> <input id="departmentNo" type="text" name="departmentNo" placeholder="请输入组织编号" class="layui-input" maxlength="255">
</div> </div>
</div> </div>
</div> </div>

View File

@ -15,7 +15,7 @@
<body> <body>
<div class="layui-fluid layui-anim layui-anim-fadein"> <div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-row layui-col-space15"> <div class="layui-row layui-col-space15">
<div class="layui-col-md2 layui-col-sm2 layui-col-xs2"> <div class="layui-col-md2 layui-col-sm2 layui-col-xs2" style="padding-right: 0px">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-body left-tree-wrap"> <div class="layui-card-body left-tree-wrap">
<div id="leftTreeWrap"> <div id="leftTreeWrap">
@ -24,7 +24,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-md10 layui-col-sm10 layui-col-xs10"> <div class="layui-col-md10 layui-col-sm10 layui-col-xs10" style="padding-left: 0px">
<div class="layui-card"> <div class="layui-card">
<div id="listContentWrap" class="layui-card-body"> <div id="listContentWrap" class="layui-card-body">
<iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe> <iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe>

View File

@ -15,7 +15,7 @@
<body> <body>
<div class="layui-fluid layui-anim layui-anim-fadein"> <div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-row layui-col-space15"> <div class="layui-row layui-col-space15">
<div class="layui-col-md2 layui-col-sm2 layui-col-xs2"> <div class="layui-col-md2 layui-col-sm2 layui-col-xs2" style="padding-right: 0px">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-body left-tree-wrap"> <div class="layui-card-body left-tree-wrap">
<div id="leftTreeWrap"> <div id="leftTreeWrap">
@ -24,7 +24,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-md10 layui-col-sm10 layui-col-xs10"> <div class="layui-col-md10 layui-col-sm10 layui-col-xs10" style="padding-left: 0px">
<div class="layui-card"> <div class="layui-card">
<div id="listContentWrap" class="layui-card-body"> <div id="listContentWrap" class="layui-card-body">
<iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe> <iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe>

View File

@ -15,7 +15,7 @@
<body> <body>
<div class="layui-fluid layui-anim layui-anim-fadein"> <div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-row layui-col-space15"> <div class="layui-row layui-col-space15">
<div class="layui-col-md2 layui-col-sm2 layui-col-xs2"> <div class="layui-col-md2 layui-col-sm2 layui-col-xs2" style="padding-right: 0px">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-body left-tree-wrap"> <div class="layui-card-body left-tree-wrap">
<div id="leftTreeWrap"> <div id="leftTreeWrap">
@ -24,7 +24,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-md10 layui-col-sm10 layui-col-xs10"> <div class="layui-col-md10 layui-col-sm10 layui-col-xs10" style="padding-left: 0px">
<div class="layui-card"> <div class="layui-card">
<div id="listContentWrap" class="layui-card-body"> <div id="listContentWrap" class="layui-card-body">
<iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe> <iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe>

View File

@ -15,7 +15,7 @@
<body> <body>
<div class="layui-fluid layui-anim layui-anim-fadein"> <div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-row layui-col-space15"> <div class="layui-row layui-col-space15">
<div class="layui-col-md2 layui-col-sm2 layui-col-xs2"> <div class="layui-col-md2 layui-col-sm2 layui-col-xs2" style="padding-right: 0px">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-body left-tree-wrap"> <div class="layui-card-body left-tree-wrap">
<div id="leftTreeWrap"> <div id="leftTreeWrap">
@ -24,7 +24,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-md10 layui-col-sm10 layui-col-xs10"> <div class="layui-col-md10 layui-col-sm10 layui-col-xs10" style="padding-left: 0px">
<div class="layui-card"> <div class="layui-card">
<div id="listContentWrap" class="layui-card-body"> <div id="listContentWrap" class="layui-card-body">
<iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe> <iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe>

View File

@ -374,6 +374,14 @@
#{excludeUserIds[${index}]} #{excludeUserIds[${index}]}
</foreach> </foreach>
</if> </if>
<if test="startTime != null and startTime != ''">
AND
LEFT(last_login_time, 10) <![CDATA[ >= ]]> #{startTime}
</if>
<if test="endTime != null and endTime != ''">
AND
LEFT(last_login_time, 10) <![CDATA[ <= ]]> #{endTime}
</if>
<if test="keywords != null and keywords != ''"> <if test="keywords != null and keywords != ''">
AND ( AND (
user_username LIKE CONCAT('%', #{keywords}, '%') user_username LIKE CONCAT('%', #{keywords}, '%')

View File

@ -20,13 +20,14 @@
<div class="test-table-reload-btn" style="margin-bottom: 10px;"> <div class="test-table-reload-btn" style="margin-bottom: 10px;">
<input type="hidden" id="userExpand" th:value="${userExpand}" th:if="${userExpand}"> <input type="hidden" id="userExpand" th:value="${userExpand}" th:if="${userExpand}">
<div class="layui-inline"> <div class="layui-inline">
<input type="text" id="keywords" class="layui-input search-item" placeholder="输入关键字"> <input type="text" id="keywords" class="layui-input search-item" placeholder="输入用户名、昵称">
</div>
最后登录
<div class="layui-inline">
<input type="text" id="startTime" class="layui-input search-item search-item-width-100" placeholder="开始时间" readonly>
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
<input type="text" id="startTime" class="layui-input search-item" placeholder="开始时间" readonly> <input type="text" id="endTime" class="layui-input search-item search-item-width-100" placeholder="结束时间" readonly>
</div>
<div class="layui-inline">
<input type="text" id="endTime" class="layui-input search-item" placeholder="结束时间" readonly>
</div> </div>
<div class="layui-btn-group"> <div class="layui-btn-group">
<button type="button" id="search" class="layui-btn layui-btn-sm"> <button type="button" id="search" class="layui-btn layui-btn-sm">

View File

@ -22,6 +22,7 @@
<div class="layui-card-body" style="padding: 15px;"> <div class="layui-card-body" style="padding: 15px;">
<form class="layui-form layui-form-pane" lay-filter="dataForm"> <form class="layui-form layui-form-pane" lay-filter="dataForm">
<div class="layui-row"> <div class="layui-row">
<div class="layui-col-md6 layui-col-sm8 layui-col-xs12">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">用户名 *</label> <label class="layui-form-label">用户名 *</label>
<div class="layui-input-block"> <div class="layui-input-block">
@ -78,16 +79,14 @@
<input type="text" name="remarks" placeholder="请输入备注" class="layui-input"> <input type="text" name="remarks" placeholder="请输入备注" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-form-item layui-form-text"> </div>
<label class="layui-form-label">头像</label> <div class="layui-col-md2 layui-col-sm4 layui-col-xs12">
<div class="layui-input-block"> <div class="layui-form-item" style="text-align: center;">
<div class="layui-textarea">
<img id="avatarImage" src="assets/images/profile-photo.jpg" title="点击修改头像"> <img id="avatarImage" src="assets/images/profile-photo.jpg" title="点击修改头像">
<input type="hidden" id="userAvatar" name="userAvatar"> <input type="hidden" id="userAvatar" name="userAvatar">
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="layui-form-item layui-layout-admin"> <div class="layui-form-item layui-layout-admin">
<div class="layui-input-block"> <div class="layui-input-block">
<div class="layui-footer" style="left: 0;"> <div class="layui-footer" style="left: 0;">

View File

@ -22,6 +22,7 @@
<div class="layui-card-body" style="padding: 15px;"> <div class="layui-card-body" style="padding: 15px;">
<form class="layui-form layui-form-pane" lay-filter="dataForm"> <form class="layui-form layui-form-pane" lay-filter="dataForm">
<div class="layui-row"> <div class="layui-row">
<div class="layui-col-md6 layui-col-sm8 layui-col-xs12">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">用户名 *</label> <label class="layui-form-label">用户名 *</label>
<div class="layui-input-block"> <div class="layui-input-block">
@ -78,16 +79,14 @@
<input type="text" name="remarks" placeholder="请输入备注" class="layui-input"> <input type="text" name="remarks" placeholder="请输入备注" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-form-item layui-form-text"> </div>
<label class="layui-form-label">头像</label> <div class="layui-col-md2 layui-col-sm4 layui-col-xs12">
<div class="layui-input-block"> <div class="layui-form-item" style="text-align: center;">
<div class="layui-textarea">
<img id="avatarImage" src="assets/images/profile-photo.jpg" title="点击修改头像"> <img id="avatarImage" src="assets/images/profile-photo.jpg" title="点击修改头像">
<input type="hidden" id="userAvatar" name="userAvatar"> <input type="hidden" id="userAvatar" name="userAvatar">
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="layui-form-item layui-layout-admin"> <div class="layui-form-item layui-layout-admin">
<div class="layui-input-block"> <div class="layui-input-block">
<div class="layui-footer" style="left: 0;"> <div class="layui-footer" style="left: 0;">