Commit 678218ce authored by WeiWei's avatar WeiWei

完善权限系统

parent 026aece9
......@@ -85,7 +85,7 @@
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<directory>${project.ba1dir}/src/main/resources</directory>
</resource>
<resource>
<directory>${project.build.directory}/generated-resources</directory>
......
......@@ -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.service.ChannelConfService;
import cn.quantgroup.cashloanflowboss.api.user.entity.boss.User;
import cn.quantgroup.cashloanflowboss.api.user.model.Pagination;
import cn.quantgroup.cashloanflowboss.core.base.Result;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -13,7 +12,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.Map;
/**
* 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;
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.entity.boss.User;
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.dictionary.ApplicationDictionary;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus;
......@@ -16,7 +15,6 @@ import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
/**
* Created by WeiWei on 2019/7/22.
......@@ -51,13 +49,16 @@ public class LogService {
// 检查密码是否正确
Assert.isFalse(user.getPassword().equalsIgnoreCase(MD5Tools.md5(password)), ApplicationStatus.USERNAME_OR_PASSWORD_ERROR);
// 创建Session
HttpSession session = this.request.getSession(true);
Permission permission = new Permission();
permission.setId("Log.logout");
permission.setAuthorities(Arrays.asList(Authority.READ));
// 设置用户主要信息
Principal principal = new Principal();
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;
......@@ -70,7 +71,7 @@ public class LogService {
*/
public boolean logout() {
this.request.getSession().removeAttribute(ApplicationDictionary.SECURITY_KEY);
this.request.getSession().removeAttribute(ApplicationDictionary.PRINCIPAL);
return true;
......
package cn.quantgroup.cashloanflowboss.api.role.entity.boss;
import cn.quantgroup.cashloanflowboss.component.security.Authority;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
......@@ -9,6 +11,8 @@ import java.util.List;
* Created by WeiWei on 2019/7/30.
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
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;
import cn.quantgroup.cashloanflowboss.api.role.entity.boss.Permission;
import cn.quantgroup.cashloanflowboss.core.persistence.Primary;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.*;
import java.util.List;
import java.util.function.UnaryOperator;
/**
* Created by WeiWei on 2019/7/30.
......@@ -15,23 +13,31 @@ import java.util.List;
@Data
@Entity
@Table(name = "role")
public class Role extends Primary {
public class Role extends Primary implements UnaryOperator<Role> {
/**
* 父角色
*/
@OneToOne
@JoinColumn(name ="parent_id")
private Role parent;
/**
* 角色名称
*/
@Column(name = "name")
private String name;
/**
* 授权列表
*/
@Transient
@Convert(converter = PermissionListConverter.class)
@Column(name = "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;
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.RoleUserRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class RoleService {
@Autowired
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;
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.core.persistence.Primary;
import lombok.Data;
import javax.persistence.*;
import java.util.Date;
import java.util.Set;
/**
* Created by WeiWei on 2019/7/22.
......@@ -27,6 +30,20 @@ public class User extends Primary {
@Column(name = "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;
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.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Component;
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.http.HttpServletRequest;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Objects;
/**
* Created by WeiWei on 2017/5/23.
......@@ -139,4 +146,17 @@ public class Application implements ApplicationContextAware, ServletContextAware
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;
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.SecurityHandler;
import cn.quantgroup.cashloanflowboss.core.Application;
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.utils.JSONTools;
import com.fasterxml.jackson.core.type.TypeReference;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
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.stream.Stream;
/**
* Created by WeiWei on 2019/7/26.
*/
@Configuration
public class ApplicationSecurityConfiguration implements SecurityHandler {
@Autowired
private HttpServletRequest request;
public class ApplicationSecurityHandler implements SecurityHandler {
@Override
public boolean doAuthentication(MethodInvocation invocation, String authorityId, Authority[] authority) throws Throwable {
// 获取Session
HttpSession session = this.request.getSession(false);
Principal principal = Application.getPrincipal();
// 检查是否已登录
Assert.isTrue((Objects.isNull(session) || Objects.isNull(session.getAttribute(ApplicationDictionary.SECURITY_KEY))), ApplicationStatus.AUTHENTICATION_FAILURE);
// 读取Session授权内容
List<Permission> permissions = JSONTools.deserialize(String.valueOf(session.getAttribute(ApplicationDictionary.SECURITY_KEY)), new TypeReference<List<Permission>>() {});
if (Objects.nonNull(permissions)) {
Assert.isNull(principal, ApplicationStatus.AUTHENTICATION_FAILURE);
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;
*/
public final class ApplicationDictionary {
// 权限Session Key
public static final String SECURITY_KEY = "PERMISSION";
/**
* 用户首要Seesion集(包含权限、角色、渠道等信息)
*/
public static final String PRINCIPAL = "PRINCIPAL";
// user Session key
public static final String USER_KEY = "USER";
......
......@@ -8,6 +8,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.Objects;
/**
* JSON工具类,默认是用Jackson
......@@ -45,11 +46,17 @@ public class JSONTools {
* @return
*/
public static <T> T deserialize(String dataString, TypeReference type) {
if (Objects.isNull(dataString)) {
return null;
}
try {
return objectMapper.readValue(dataString, type);
} catch (IOException e) {
throw new ApplicationException(ApplicationStatus.JSON_DATA_EXCEPTION, e.getMessage());
}
}
/**
......@@ -61,11 +68,17 @@ public class JSONTools {
* @return
*/
public static <T> T deserialize(String dataString, Class<T> type) {
if (Objects.isNull(dataString)) {
return null;
}
try {
return objectMapper.readValue(dataString, type);
} catch (IOException e) {
throw new ApplicationException(ApplicationStatus.JSON_DATA_EXCEPTION, e.getMessage());
}
}
/**
......
......@@ -10,7 +10,7 @@
<logger name="cn.quantgroup" level="DEBUG" />
<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="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