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

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.position.PositionSimpleDTO;
import ink.wgink.pojo.dtos.role.RoleSimpleDTO;
import org.springframework.security.core.CredentialsContainer;
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.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
/**
* @ClassName: UserBO
@ -18,7 +22,19 @@ import java.util.List;
* @Date: 2019/2/20 2:22 PM
* @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 userName;
@ -39,16 +55,218 @@ public class LoginUser extends User {
*/
private Object expandData;
public LoginUser() {
super("", "", null);
public LoginUser(String username, String password) {
this(username, password, true, true, true, true);
}
public LoginUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
public LoginUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked) {
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) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
public void setAuthorities(Set<GrantedAuthority> 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() {
@ -171,4 +389,5 @@ public class LoginUser extends User {
public void setExpandData(Object expandData) {
this.expandData = expandData;
}
}

View File

@ -1,17 +1,44 @@
package ink.wgink.login.base.authentication.user;
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.exceptions.UserAuthenticationException;
import ink.wgink.login.base.service.user.UserLoginService;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
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
* 当你想要放弃的时候想想当初你为何开始
@ -23,27 +50,158 @@ import org.springframework.security.crypto.password.PasswordEncoder;
* @Version: 1.0
**/
public class UserAuthenticationProvider implements AuthenticationProvider {
private static final Logger LOG = LoggerFactory.getLogger(UserAuthenticationProvider.class);
private UserDetailsService userDetailsService;
private PasswordEncoder passwordEncoder;
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
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
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())) {
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())) {
userLoginService.setUserDataAuthority(loginUser);
}
// 更新登录信息
userLoginService.updateUserLoginInfo(loginUser.getUserId(), loginUser.getUserName(), LoginTypeEnum.USERNAME_AND_PASSWORD.getValue());
UserAuthenticationToken userAuthenticationTokenResult = new UserAuthenticationToken(loginUser, null, loginUser.getAuthorities());
userAuthenticationTokenResult.setDetails(userAuthenticationToken.getDetails());
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
public boolean supports(Class<?> authentication) {
return UserAuthenticationToken.class.isAssignableFrom(authentication);
@ -60,4 +218,40 @@ public class UserAuthenticationProvider implements AuthenticationProvider {
public void setUserLoginService(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 {
String ERROR = "error";
String LOGIN_USERNAME = "loginUsername";
/**
* 错误信息
*/

View File

@ -1,12 +1,20 @@
package ink.wgink.login.base.security;
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.LogoutHandler;
import ink.wgink.login.base.security.user.UserSecurityConfig;
import ink.wgink.login.base.service.user.UserDetailServiceImpl;
import ink.wgink.login.base.service.user.UserLoginService;
import ink.wgink.properties.AccessControlProperties;
import ink.wgink.properties.BaseProperties;
import ink.wgink.service.department.service.IDepartmentUserService;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
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.password.PasswordEncoder;
import javax.servlet.http.HttpSession;
/**
* @ClassName: WebSecurityConfig
* @Description: security配置
@ -34,6 +44,24 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private UserDetailServiceImpl userDetailService;
@Autowired
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
protected void configure(HttpSecurity http) throws Exception {
@ -107,6 +135,15 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
userSecurityConfig.setLoginProcessUrl(baseProperties.getLoginProcess());
userSecurityConfig.setLoginFailureHandler(loginFailureHandler);
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);
}

View File

@ -1,10 +1,18 @@
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.UserAuthenticationProvider;
import ink.wgink.login.base.handler.LoginFailureHandler;
import ink.wgink.login.base.service.user.UserDetailServiceImpl;
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.config.annotation.SecurityConfigurerAdapter;
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.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpSession;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
@ -29,6 +39,15 @@ public class UserSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurit
private String loginProcessUrl;
private PasswordEncoder passwordEncoder;
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
public void configure(HttpSecurity http) throws Exception {
@ -42,6 +61,15 @@ public class UserSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurit
userAuthenticationProvider.setPasswordEncoder(passwordEncoder);
userAuthenticationProvider.setUserDetailsService(userDetailService);
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之前
http.authenticationProvider(userAuthenticationProvider).addFilterBefore(userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
@ -65,4 +93,40 @@ public class UserSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurit
public void setUserLoginService(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> pageParams = new HashMap<>(16);
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());
// 系统LOGO

View File

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

View File

@ -2,44 +2,22 @@ package ink.wgink.login.base.service.user;
import com.alibaba.fastjson.JSONObject;
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.login.base.consts.IUserCenterConst;
import ink.wgink.login.base.exceptions.UserAuthenticationException;
import ink.wgink.login.base.manager.ConfigManager;
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.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.Map;
/**
* @ClassName: UserDetailServiceImpl
@ -51,28 +29,8 @@ import java.util.*;
@Service
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
private IUserService userService;
@Autowired
private AccessControlProperties accessControlProperties;
@Autowired
private HttpSession httpSession;
public UserDetailServiceImpl() {
super();
@ -95,85 +53,24 @@ public class UserDetailServiceImpl implements UserDetailsService, IUserDetailChe
if (userPO.getUserState() == 1) {
throw new UserAuthenticationException("账号已冻结");
}
LOG.debug("设置权限权限");
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("登录异常");
}
if (isAccountExpired(userPO)) {
throw new UserAuthenticationException("账号已经过期");
}
return createUserBO(userPO);
}
/**
* 创建UserBO
*
* @param userPO
* @param grantedAuthorities
* @return
*/
private LoginUser createUserBO(UserPO userPO, Set<GrantedAuthority> grantedAuthorities) {
private LoginUser createUserBO(UserPO userPO) {
LoginUser loginUser = new LoginUser(userPO.getUserUsername(), userPO.getUserPassword(),
userPO.getUserType() == 1 ? true : false,
isAccountNonExpired(userPO),
isCredentialsNonExpired(userPO),
userPO.getUserState() == 0 ? true : false, grantedAuthorities);
userPO.getUserState() == 0 ? true : false);
loginUser.setUserId(userPO.getUserId());
loginUser.setUserName(userPO.getUserName());
loginUser.setUserPhone(userPO.getUserPhone());
@ -235,58 +132,21 @@ public class UserDetailServiceImpl implements UserDetailsService, IUserDetailChe
}
/**
* 角色授权列表
* 账号是否过期
*
* @param rolePOs
* @param userPO
* @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));
});
private boolean isAccountExpired(UserPO userPO) {
if (StringUtils.isBlank(userPO.getUserExpiredDate())) {
return false;
}
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
FROM
sys_login_form
WHERE
is_delete = 0
<if test="keywords != null and keywords != ''">
AND
name LIKE CONCAT('%', #{keywords}, '%')
</if>
</select>
<!-- 登录form表单详情 -->
@ -182,10 +188,13 @@
FROM
sys_login_form
WHERE
is_delete = 0
<if test="loginFormId != null and loginFormId != ''">
AND
loginform_id = #{loginFormId}
</if>
<if test="isActive != null">
AND
is_active = #{isActive}
</if>
</select>

View File

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

View File

@ -28,6 +28,16 @@
</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-form-item">
<label class="layui-form-label">名称(英文)</label>
@ -36,8 +46,6 @@
</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item">
<label class="layui-form-label">名称(其他)</label>
@ -46,6 +54,8 @@
</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item">
<label class="layui-form-label">组织类型 *</label>

View File

@ -34,6 +34,16 @@
</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-form-item">
<label class="layui-form-label">名称(英文)</label>
@ -42,8 +52,6 @@
</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item">
<label class="layui-form-label">名称(其他)</label>
@ -52,6 +60,8 @@
</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12">
<div class="layui-form-item">
<label class="layui-form-label">组织类型 *</label>

View File

@ -65,7 +65,7 @@
<div class="layui-form-item">
<label class="layui-form-label">编号</label>
<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>

View File

@ -65,7 +65,7 @@
<div class="layui-form-item">
<label class="layui-form-label">编号</label>
<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>

View File

@ -15,7 +15,7 @@
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<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-body left-tree-wrap">
<div id="leftTreeWrap">
@ -24,7 +24,7 @@
</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 id="listContentWrap" class="layui-card-body">
<iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe>

View File

@ -15,7 +15,7 @@
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<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-body left-tree-wrap">
<div id="leftTreeWrap">
@ -24,7 +24,7 @@
</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 id="listContentWrap" class="layui-card-body">
<iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe>

View File

@ -15,7 +15,7 @@
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<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-body left-tree-wrap">
<div id="leftTreeWrap">
@ -24,7 +24,7 @@
</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 id="listContentWrap" class="layui-card-body">
<iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe>

View File

@ -15,7 +15,7 @@
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<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-body left-tree-wrap">
<div id="leftTreeWrap">
@ -24,7 +24,7 @@
</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 id="listContentWrap" class="layui-card-body">
<iframe id="listContent" frameborder="0" class="layadmin-iframe"></iframe>

View File

@ -374,6 +374,14 @@
#{excludeUserIds[${index}]}
</foreach>
</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 != ''">
AND (
user_username LIKE CONCAT('%', #{keywords}, '%')

View File

@ -20,13 +20,14 @@
<div class="test-table-reload-btn" style="margin-bottom: 10px;">
<input type="hidden" id="userExpand" th:value="${userExpand}" th:if="${userExpand}">
<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 class="layui-inline">
<input type="text" id="startTime" class="layui-input search-item" placeholder="开始时间" readonly>
</div>
<div class="layui-inline">
<input type="text" id="endTime" 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-btn-group">
<button type="button" id="search" class="layui-btn layui-btn-sm">

View File

@ -22,70 +22,69 @@
<div class="layui-card-body" style="padding: 15px;">
<form class="layui-form layui-form-pane" lay-filter="dataForm">
<div class="layui-row">
<div class="layui-form-item">
<label class="layui-form-label">用户名 *</label>
<div class="layui-input-block">
<input type="text" name="userUsername" lay-verify="userUsername" placeholder="请输入用户名" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密码 *</label>
<div class="layui-input-block">
<input type="password" name="userPassword" lay-verify="required" placeholder="请输入密码" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">昵称 *</label>
<div class="layui-input-block">
<input type="text" name="userName" lay-verify="required" placeholder="请输入昵称" class="layui-input">
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">类型 *</label>
<div class="layui-input-block">
<input type="radio" name="userType" value="1" title="系统用户">
<input type="radio" name="userType" value="2" title="普通用户" checked>
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">状态 *</label>
<div class="layui-input-block">
<input type="radio" name="userState" value="0" title="正常" checked>
<input type="radio" name="userState" value="1" title="锁定">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">手机</label>
<div class="layui-input-block">
<input type="number" name="userPhone" placeholder="请输入手机" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱</label>
<div class="layui-input-block">
<input type="text" name="userEmail" placeholder="请输入邮箱" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">过期时间</label>
<div class="layui-input-block">
<input type="text" name="userExpiredDate" id="userExpiredDate" placeholder="请选择过期日期,空表示永不过期" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">备注</label>
<div class="layui-input-block">
<input type="text" name="remarks" placeholder="请输入备注" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">头像</label>
<div class="layui-input-block">
<div class="layui-textarea">
<img id="avatarImage" src="assets/images/profile-photo.jpg" title="点击修改头像">
<input type="hidden" id="userAvatar" name="userAvatar">
<div class="layui-col-md6 layui-col-sm8 layui-col-xs12">
<div class="layui-form-item">
<label class="layui-form-label">用户名 *</label>
<div class="layui-input-block">
<input type="text" name="userUsername" lay-verify="userUsername" placeholder="请输入用户名" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密码 *</label>
<div class="layui-input-block">
<input type="password" name="userPassword" lay-verify="required" placeholder="请输入密码" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">昵称 *</label>
<div class="layui-input-block">
<input type="text" name="userName" lay-verify="required" placeholder="请输入昵称" class="layui-input">
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">类型 *</label>
<div class="layui-input-block">
<input type="radio" name="userType" value="1" title="系统用户">
<input type="radio" name="userType" value="2" title="普通用户" checked>
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">状态 *</label>
<div class="layui-input-block">
<input type="radio" name="userState" value="0" title="正常" checked>
<input type="radio" name="userState" value="1" title="锁定">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">手机</label>
<div class="layui-input-block">
<input type="number" name="userPhone" placeholder="请输入手机" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱</label>
<div class="layui-input-block">
<input type="text" name="userEmail" placeholder="请输入邮箱" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">过期时间</label>
<div class="layui-input-block">
<input type="text" name="userExpiredDate" id="userExpiredDate" placeholder="请选择过期日期,空表示永不过期" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">备注</label>
<div class="layui-input-block">
<input type="text" name="remarks" placeholder="请输入备注" class="layui-input">
</div>
</div>
</div>
<div class="layui-col-md2 layui-col-sm4 layui-col-xs12">
<div class="layui-form-item" style="text-align: center;">
<img id="avatarImage" src="assets/images/profile-photo.jpg" title="点击修改头像">
<input type="hidden" id="userAvatar" name="userAvatar">
</div>
</div>
</div>
<div class="layui-form-item layui-layout-admin">

View File

@ -22,70 +22,69 @@
<div class="layui-card-body" style="padding: 15px;">
<form class="layui-form layui-form-pane" lay-filter="dataForm">
<div class="layui-row">
<div class="layui-form-item">
<label class="layui-form-label">用户名 *</label>
<div class="layui-input-block">
<input type="text" name="userUsername" lay-verify="userUsername" placeholder="请输入用户名" class="layui-input" readonly>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">新密码</label>
<div class="layui-input-block">
<input type="password" name="userPassword" placeholder="修改密码,请输入新密码,不修改为空" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">昵称 *</label>
<div class="layui-input-block">
<input type="text" name="userName" lay-verify="required" placeholder="请输入昵称" class="layui-input">
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">类型 *</label>
<div class="layui-input-block">
<input type="radio" name="userType" value="1" title="系统用户">
<input type="radio" name="userType" value="2" title="普通用户">
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">状态 *</label>
<div class="layui-input-block">
<input type="radio" name="userState" value="0" title="正常">
<input type="radio" name="userState" value="1" title="锁定">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">手机</label>
<div class="layui-input-block">
<input type="number" name="userPhone" placeholder="请输入手机" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱</label>
<div class="layui-input-block">
<input type="text" name="userEmail" placeholder="请输入邮箱" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">过期时间</label>
<div class="layui-input-block">
<input type="text" name="userExpiredDate" id="userExpiredDate" placeholder="请选择过期日期,空表示永不过期" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">备注</label>
<div class="layui-input-block">
<input type="text" name="remarks" placeholder="请输入备注" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">头像</label>
<div class="layui-input-block">
<div class="layui-textarea">
<img id="avatarImage" src="assets/images/profile-photo.jpg" title="点击修改头像">
<input type="hidden" id="userAvatar" name="userAvatar">
<div class="layui-col-md6 layui-col-sm8 layui-col-xs12">
<div class="layui-form-item">
<label class="layui-form-label">用户名 *</label>
<div class="layui-input-block">
<input type="text" name="userUsername" lay-verify="userUsername" placeholder="请输入用户名" class="layui-input" readonly>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">新密码</label>
<div class="layui-input-block">
<input type="password" name="userPassword" placeholder="修改密码,请输入新密码,不修改为空" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">昵称 *</label>
<div class="layui-input-block">
<input type="text" name="userName" lay-verify="required" placeholder="请输入昵称" class="layui-input">
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">类型 *</label>
<div class="layui-input-block">
<input type="radio" name="userType" value="1" title="系统用户">
<input type="radio" name="userType" value="2" title="普通用户">
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">状态 *</label>
<div class="layui-input-block">
<input type="radio" name="userState" value="0" title="正常">
<input type="radio" name="userState" value="1" title="锁定">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">手机</label>
<div class="layui-input-block">
<input type="number" name="userPhone" placeholder="请输入手机" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱</label>
<div class="layui-input-block">
<input type="text" name="userEmail" placeholder="请输入邮箱" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">过期时间</label>
<div class="layui-input-block">
<input type="text" name="userExpiredDate" id="userExpiredDate" placeholder="请选择过期日期,空表示永不过期" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">备注</label>
<div class="layui-input-block">
<input type="text" name="remarks" placeholder="请输入备注" class="layui-input">
</div>
</div>
</div>
<div class="layui-col-md2 layui-col-sm4 layui-col-xs12">
<div class="layui-form-item" style="text-align: center;">
<img id="avatarImage" src="assets/images/profile-photo.jpg" title="点击修改头像">
<input type="hidden" id="userAvatar" name="userAvatar">
</div>
</div>
</div>
<div class="layui-form-item layui-layout-admin">