Commit 678218ce authored by WeiWei's avatar WeiWei

完善权限系统

parent 026aece9
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
<build> <build>
<resources> <resources>
<resource> <resource>
<directory>${project.basedir}/src/main/resources</directory> <directory>${project.ba1dir}/src/main/resources</directory>
</resource> </resource>
<resource> <resource>
<directory>${project.build.directory}/generated-resources</directory> <directory>${project.build.directory}/generated-resources</directory>
......
...@@ -2,7 +2,6 @@ package cn.quantgroup.cashloanflowboss.api.channel.controller; ...@@ -2,7 +2,6 @@ package cn.quantgroup.cashloanflowboss.api.channel.controller;
import cn.quantgroup.cashloanflowboss.api.channel.entity.clf.ChannelConfiguration; import cn.quantgroup.cashloanflowboss.api.channel.entity.clf.ChannelConfiguration;
import cn.quantgroup.cashloanflowboss.api.channel.service.ChannelConfService; import cn.quantgroup.cashloanflowboss.api.channel.service.ChannelConfService;
import cn.quantgroup.cashloanflowboss.api.user.entity.boss.User;
import cn.quantgroup.cashloanflowboss.api.user.model.Pagination; import cn.quantgroup.cashloanflowboss.api.user.model.Pagination;
import cn.quantgroup.cashloanflowboss.core.base.Result; import cn.quantgroup.cashloanflowboss.core.base.Result;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -13,7 +12,6 @@ import org.springframework.web.bind.annotation.RequestParam; ...@@ -13,7 +12,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.Map;
/** /**
* Created with suntao on 2019/8/2 * Created with suntao on 2019/8/2
......
package cn.quantgroup.cashloanflowboss.api.log.model;
/**
* Created by WeiWei on 2019/7/26.
*/
public class Permission {
}
package cn.quantgroup.cashloanflowboss.api.log.model;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.Role;
import cn.quantgroup.cashloanflowboss.api.user.dictionary.UserRank;
import lombok.Data;
import java.util.Objects;
import java.util.Set;
/**
* Created by WeiWei on 2019/7/26.
*/
@Data
public class Principal {
/**
* 用户ID
*/
private Long userId;
/**
* 用户级别
*/
private UserRank rank;
/**
* 所属渠道ID
*/
private String channelId;
/**
* 角色列表
*/
private Set<Role> roles;
/**
* 是否是超级管理员
*
* @return
*/
public boolean isSuperAdministrator() {
return Objects.nonNull(this.rank) && UserRank.SUPER_ADMINISTRATOR.equals(this.rank);
}
/**
* 是否管理员
*
* @return
*/
public boolean isAdministrator() {
return Objects.nonNull(this.rank) && UserRank.ADMINISTRATOR.equals(this.rank);
}
/**
* 是否操作员
*
* @return
*/
public boolean isOperator() {
return Objects.nonNull(this.rank) && UserRank.OPERATOR.equals(this.rank);
}
/**
* 是否渠道的
*
* @return
*/
public boolean isChannel() {
return Objects.nonNull(this.rank) && UserRank.CHANNEL.equals(this.rank);
}
}
package cn.quantgroup.cashloanflowboss.api.log.model;
/**
* Created by WeiWei on 2019/7/26.
*/
public class UserInformation {
private String username;
private Permission authority;
}
package cn.quantgroup.cashloanflowboss.api.log.service; package cn.quantgroup.cashloanflowboss.api.log.service;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.Permission; import cn.quantgroup.cashloanflowboss.api.log.model.Principal;
import cn.quantgroup.cashloanflowboss.api.user.dictionary.UserStatus; import cn.quantgroup.cashloanflowboss.api.user.dictionary.UserStatus;
import cn.quantgroup.cashloanflowboss.api.user.entity.boss.User; import cn.quantgroup.cashloanflowboss.api.user.entity.boss.User;
import cn.quantgroup.cashloanflowboss.api.user.service.UserService; import cn.quantgroup.cashloanflowboss.api.user.service.UserService;
import cn.quantgroup.cashloanflowboss.component.security.Authority;
import cn.quantgroup.cashloanflowboss.core.asserts.Assert; import cn.quantgroup.cashloanflowboss.core.asserts.Assert;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationDictionary; import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationDictionary;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus; import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus;
...@@ -16,7 +15,6 @@ import org.springframework.stereotype.Service; ...@@ -16,7 +15,6 @@ import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import java.util.Arrays;
/** /**
* Created by WeiWei on 2019/7/22. * Created by WeiWei on 2019/7/22.
...@@ -51,13 +49,16 @@ public class LogService { ...@@ -51,13 +49,16 @@ public class LogService {
// 检查密码是否正确 // 检查密码是否正确
Assert.isFalse(user.getPassword().equalsIgnoreCase(MD5Tools.md5(password)), ApplicationStatus.USERNAME_OR_PASSWORD_ERROR); Assert.isFalse(user.getPassword().equalsIgnoreCase(MD5Tools.md5(password)), ApplicationStatus.USERNAME_OR_PASSWORD_ERROR);
// 创建Session
HttpSession session = this.request.getSession(true); HttpSession session = this.request.getSession(true);
Permission permission = new Permission(); // 设置用户主要信息
permission.setId("Log.logout"); Principal principal = new Principal();
permission.setAuthorities(Arrays.asList(Authority.READ)); principal.setUserId(user.getId());
principal.setRank(user.getRank());
principal.setRoles(user.getRoles());
session.setAttribute(ApplicationDictionary.SECURITY_KEY, JSONTools.serialize(Arrays.asList(permission))); session.setAttribute(ApplicationDictionary.PRINCIPAL, JSONTools.serialize(principal));
return true; return true;
...@@ -70,7 +71,7 @@ public class LogService { ...@@ -70,7 +71,7 @@ public class LogService {
*/ */
public boolean logout() { public boolean logout() {
this.request.getSession().removeAttribute(ApplicationDictionary.SECURITY_KEY); this.request.getSession().removeAttribute(ApplicationDictionary.PRINCIPAL);
return true; return true;
......
package cn.quantgroup.cashloanflowboss.api.role.entity.boss; package cn.quantgroup.cashloanflowboss.api.role.entity.boss;
import cn.quantgroup.cashloanflowboss.component.security.Authority; import cn.quantgroup.cashloanflowboss.component.security.Authority;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List; import java.util.List;
...@@ -9,6 +11,8 @@ import java.util.List; ...@@ -9,6 +11,8 @@ import java.util.List;
* Created by WeiWei on 2019/7/30. * Created by WeiWei on 2019/7/30.
*/ */
@Data @Data
@NoArgsConstructor
@AllArgsConstructor
public class Permission { public class Permission {
/** /**
......
package cn.quantgroup.cashloanflowboss.api.role.entity.boss;
import cn.quantgroup.cashloanflowboss.utils.JSONTools;
import com.fasterxml.jackson.core.type.TypeReference;
import javax.persistence.AttributeConverter;
import java.util.List;
import java.util.Objects;
/**
* Created by WeiWei on 2019/8/9.
*/
public class PermissionListConverter implements AttributeConverter<List<Permission>, String> {
@Override
public String convertToDatabaseColumn(List<Permission> permissions) {
return JSONTools.serialize(permissions);
}
@Override
public List<Permission> convertToEntityAttribute(String data) {
return Objects.nonNull(data) && !data.isEmpty() ? JSONTools.deserialize(data, new TypeReference<List<Permission>>() {}) : null;
}
}
package cn.quantgroup.cashloanflowboss.api.role.entity.boss; package cn.quantgroup.cashloanflowboss.api.role.entity.boss;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.Permission;
import cn.quantgroup.cashloanflowboss.core.persistence.Primary; import cn.quantgroup.cashloanflowboss.core.persistence.Primary;
import lombok.Data; import lombok.Data;
import javax.persistence.Entity; import javax.persistence.*;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.List; import java.util.List;
import java.util.function.UnaryOperator;
/** /**
* Created by WeiWei on 2019/7/30. * Created by WeiWei on 2019/7/30.
...@@ -15,23 +13,31 @@ import java.util.List; ...@@ -15,23 +13,31 @@ import java.util.List;
@Data @Data
@Entity @Entity
@Table(name = "role") @Table(name = "role")
public class Role extends Primary { public class Role extends Primary implements UnaryOperator<Role> {
/** /**
* 父角色 * 父角色
*/ */
@OneToOne
@JoinColumn(name ="parent_id")
private Role parent; private Role parent;
/** /**
* 角色名称 * 角色名称
*/ */
@Column(name = "name")
private String name; private String name;
/** /**
* 授权列表 * 授权列表
*/ */
@Transient @Convert(converter = PermissionListConverter.class)
@Column(name = "permissions")
private List<Permission> permissions; private List<Permission> permissions;
@Override
public Role apply(Role role) {
return this.getParent();
}
} }
package cn.quantgroup.cashloanflowboss.api.role.entity.boss;
import cn.quantgroup.cashloanflowboss.core.persistence.Primary;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Table;
@Data
@Entity
@Table(name = "role_user")
public class RoleUser extends Primary {
private Long roleId;
private Long userId;
}
package cn.quantgroup.cashloanflowboss.api.role.repository.boss;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.RoleUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface RoleUserRepository extends JpaRepository<RoleUser, Long> {
RoleUser findByUserId(Long userId);
}
package cn.quantgroup.cashloanflowboss.api.role.service; package cn.quantgroup.cashloanflowboss.api.role.service;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.Role; import cn.quantgroup.cashloanflowboss.api.role.entity.boss.Role;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.RoleUser;
import cn.quantgroup.cashloanflowboss.api.role.repository.boss.RoleRepository; import cn.quantgroup.cashloanflowboss.api.role.repository.boss.RoleRepository;
import cn.quantgroup.cashloanflowboss.api.role.repository.boss.RoleUserRepository;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j @Slf4j
@Service @Service
public class RoleService { public class RoleService {
@Autowired @Autowired
private RoleRepository roleRepository; private RoleRepository roleRepository;
@Autowired
private RoleUserRepository roleUserRepository;
public Role findRoleByUserId(Long userId) {
RoleUser roleUser = roleUserRepository.findByUserId(userId);
Long roleId = roleUser.getRoleId();
Role role = findRoleByRoleId(roleId);
return role;
}
public Role findRoleByRoleId(Long roleId) { /**
return roleRepository.findOne(roleId); * 获取用户角色列表
*
* @param ids 角色ID
* @return
*/
public List<Role> getRoles(List<Long> ids) {
return this.roleRepository.findAll(ids);
} }
} }
package cn.quantgroup.cashloanflowboss.api.user.dictionary;
/**
* Created by WeiWei on 2019/8/9.
*/
public enum UserRank {
/**
* 超级管理员(本级别直接跳过权限验证)
*/
SUPER_ADMINISTRATOR,
/**
* 管理员(可选择性跳过验证部分权限,同时需要详细授权内容)
*/
ADMINISTRATOR,
/**
* 操作员(仅能使用授权验证)
*/
OPERATOR,
/**
* 渠道(仅能使用授权验证,且不具备渠道切换)
*/
CHANNEL
}
package cn.quantgroup.cashloanflowboss.api.user.entity.boss; package cn.quantgroup.cashloanflowboss.api.user.entity.boss;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.Role;
import cn.quantgroup.cashloanflowboss.api.user.dictionary.UserRank;
import cn.quantgroup.cashloanflowboss.api.user.dictionary.UserStatus; import cn.quantgroup.cashloanflowboss.api.user.dictionary.UserStatus;
import cn.quantgroup.cashloanflowboss.core.persistence.Primary; import cn.quantgroup.cashloanflowboss.core.persistence.Primary;
import lombok.Data; import lombok.Data;
import javax.persistence.*; import javax.persistence.*;
import java.util.Date; import java.util.Date;
import java.util.Set;
/** /**
* Created by WeiWei on 2019/7/22. * Created by WeiWei on 2019/7/22.
...@@ -27,6 +30,20 @@ public class User extends Primary { ...@@ -27,6 +30,20 @@ public class User extends Primary {
@Column(name = "password") @Column(name = "password")
private String password; private String password;
/**
* 用户级别
*/
@Enumerated(EnumType.STRING)
@Column(name = "rank")
private UserRank rank;
/**
* 用户角色列表
*/
@OneToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_role_mapping", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
/** /**
* 用户状态 * 用户状态
*/ */
......
package cn.quantgroup.cashloanflowboss.core; package cn.quantgroup.cashloanflowboss.core;
import cn.quantgroup.cashloanflowboss.api.log.model.Principal;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationDictionary;
import cn.quantgroup.cashloanflowboss.utils.JSONTools;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.context.ServletContextAware; import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Validation; import javax.validation.Validation;
import javax.validation.Validator; import javax.validation.Validator;
import java.util.Objects;
/** /**
* Created by WeiWei on 2017/5/23. * Created by WeiWei on 2017/5/23.
...@@ -139,4 +146,17 @@ public class Application implements ApplicationContextAware, ServletContextAware ...@@ -139,4 +146,17 @@ public class Application implements ApplicationContextAware, ServletContextAware
return Validation.buildDefaultValidatorFactory().getValidator(); return Validation.buildDefaultValidatorFactory().getValidator();
} }
/**
* 获取用户主要信息
*
* @return
*/
public static Principal getPrincipal() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return Objects.nonNull(request) && Objects.nonNull(request.getSession()) ? JSONTools.deserialize(String.valueOf(request.getSession().getAttribute(ApplicationDictionary.PRINCIPAL)), Principal.class) : null;
}
} }
\ No newline at end of file
package cn.quantgroup.cashloanflowboss.core.configuration; package cn.quantgroup.cashloanflowboss.core.configuration;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.Permission; import cn.quantgroup.cashloanflowboss.api.log.model.Principal;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.Role;
import cn.quantgroup.cashloanflowboss.component.security.Authority; import cn.quantgroup.cashloanflowboss.component.security.Authority;
import cn.quantgroup.cashloanflowboss.component.security.SecurityHandler; import cn.quantgroup.cashloanflowboss.component.security.SecurityHandler;
import cn.quantgroup.cashloanflowboss.core.Application;
import cn.quantgroup.cashloanflowboss.core.asserts.Assert; import cn.quantgroup.cashloanflowboss.core.asserts.Assert;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationDictionary;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus; import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus;
import cn.quantgroup.cashloanflowboss.utils.JSONTools;
import com.fasterxml.jackson.core.type.TypeReference;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Stream;
/** /**
* Created by WeiWei on 2019/7/26. * Created by WeiWei on 2019/7/26.
*/ */
@Configuration @Configuration
public class ApplicationSecurityConfiguration implements SecurityHandler { public class ApplicationSecurityHandler implements SecurityHandler {
@Autowired
private HttpServletRequest request;
@Override @Override
public boolean doAuthentication(MethodInvocation invocation, String authorityId, Authority[] authority) throws Throwable { public boolean doAuthentication(MethodInvocation invocation, String authorityId, Authority[] authority) throws Throwable {
// 获取Session Principal principal = Application.getPrincipal();
HttpSession session = this.request.getSession(false);
// 检查是否已登录 // 检查是否已登录
Assert.isTrue((Objects.isNull(session) || Objects.isNull(session.getAttribute(ApplicationDictionary.SECURITY_KEY))), ApplicationStatus.AUTHENTICATION_FAILURE); Assert.isNull(principal, ApplicationStatus.AUTHENTICATION_FAILURE);
// 读取Session授权内容
List<Permission> permissions = JSONTools.deserialize(String.valueOf(session.getAttribute(ApplicationDictionary.SECURITY_KEY)), new TypeReference<List<Permission>>() {});
if (Objects.nonNull(permissions)) {
Permission permission = permissions.parallelStream().filter(p2 -> p2.getId().equals(authorityId)).findFirst().orElseThrow(ApplicationStatus.INVALID_AUTHORITY::throwException); // 如果是超级管理员跳过权限验证
return principal.isSuperAdministrator() || principal.getRoles().stream().anyMatch(role -> Stream.iterate(role, Role::getParent).anyMatch(_role -> this.checkAuthority(authorityId, _role)));
return !(Objects.isNull(permission.getAuthorities()) || permission.getAuthorities().isEmpty()) && permission.getAuthorities().parallelStream().anyMatch(a -> Arrays.asList(authority).contains(a)); }
}
return false;
/**
* 检查权限
*
* @param authorityId
* @param role
* @return
*/
private boolean checkAuthority(String authorityId, Role role) {
return Objects.nonNull(role.getPermissions()) && role.getPermissions().parallelStream().anyMatch(permission -> permission.getId().equals(authorityId));
} }
} }
...@@ -7,8 +7,11 @@ package cn.quantgroup.cashloanflowboss.core.dictionary; ...@@ -7,8 +7,11 @@ package cn.quantgroup.cashloanflowboss.core.dictionary;
*/ */
public final class ApplicationDictionary { public final class ApplicationDictionary {
// 权限Session Key /**
public static final String SECURITY_KEY = "PERMISSION"; * 用户首要Seesion集(包含权限、角色、渠道等信息)
*/
public static final String PRINCIPAL = "PRINCIPAL";
// user Session key // user Session key
public static final String USER_KEY = "USER"; public static final String USER_KEY = "USER";
......
...@@ -8,6 +8,7 @@ import com.fasterxml.jackson.core.type.TypeReference; ...@@ -8,6 +8,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
/** /**
* JSON工具类,默认是用Jackson * JSON工具类,默认是用Jackson
...@@ -45,11 +46,17 @@ public class JSONTools { ...@@ -45,11 +46,17 @@ public class JSONTools {
* @return * @return
*/ */
public static <T> T deserialize(String dataString, TypeReference type) { public static <T> T deserialize(String dataString, TypeReference type) {
if (Objects.isNull(dataString)) {
return null;
}
try { try {
return objectMapper.readValue(dataString, type); return objectMapper.readValue(dataString, type);
} catch (IOException e) { } catch (IOException e) {
throw new ApplicationException(ApplicationStatus.JSON_DATA_EXCEPTION, e.getMessage()); throw new ApplicationException(ApplicationStatus.JSON_DATA_EXCEPTION, e.getMessage());
} }
} }
/** /**
...@@ -61,11 +68,17 @@ public class JSONTools { ...@@ -61,11 +68,17 @@ public class JSONTools {
* @return * @return
*/ */
public static <T> T deserialize(String dataString, Class<T> type) { public static <T> T deserialize(String dataString, Class<T> type) {
if (Objects.isNull(dataString)) {
return null;
}
try { try {
return objectMapper.readValue(dataString, type); return objectMapper.readValue(dataString, type);
} catch (IOException e) { } catch (IOException e) {
throw new ApplicationException(ApplicationStatus.JSON_DATA_EXCEPTION, e.getMessage()); throw new ApplicationException(ApplicationStatus.JSON_DATA_EXCEPTION, e.getMessage());
} }
} }
/** /**
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<logger name="cn.quantgroup" level="DEBUG" /> <logger name="cn.quantgroup" level="DEBUG" />
<logger name="org.springframework" level="INFO" /> <logger name="org.springframework" level="INFO" />
<logger name="org.hibernate" level="warn"/> <logger name="org.hibernate" level="debug"/>
<logger name="org.apache" level="warn"/> <logger name="org.apache" level="warn"/>
<logger name="ch.qos.logback" level="warn"/> <logger name="ch.qos.logback" level="warn"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment