# Heimdall 配置

从本章开始,我们将基于权限管理框架,逐步实现认证和授权功能。

# 实现 UserDetails

UserDetails 接口规定了认证授权的凭据格式,Heimdall 框架通过 UserDetails 确定唯一用户以及对用户信息进行缓存。 为了便于后续使用,在 UserDetails 中,可以附着自定义对象。 本例中,我们定义的 UserDetails 如下:


/**
 * 自定义用户详情实体
 *
 * @author Luter
 * @see UserDetails
 * @see DefaultSimpleUserDetails
 */
@Data
@EqualsAndHashCode
@Accessors(chain = true)
@AllArgsConstructor
public class AppUserDetails implements UserDetails {
    /**
     * The User.
     */
    private SysUserDTO user;
    /**
     * The Principal.
     */
    private String principal;

    /**
     * Instantiates a new Default user detail.
     *
     * @param user the user
     */
    public AppUserDetails(SysUserDTO user) {
        this.user = user;
    }

    @Override
    public String getPrincipal() {
        return "APP:" + user.getId();
    }

    @Override
    public boolean enabled() {
        return user.getEnabled();
    }

    /**
     * Gets user.
     *
     * @return the user
     */
    public SysUserDTO getUser() {
        return user;
    }

    /**
     * Sets user.
     *
     * @param user the user
     */
    public void setUser(SysUserDTO user) {
        this.user = user;
    }

    /**
     * Sets principal.
     *
     * @param principal the principal
     */
    public void setPrincipal(String principal) {
        this.principal = principal;
    }


}

其中:getPrincipal()和 enabled()接口方法必须实现,以便 Heimdall 框架知道”是谁“以及"是否可用"

Heimdall 框架会将AppUserDetails 类信息,以 JSON 格式进行缓存。

# 实现 AuthorizationMetaDataService

AuthorizationMetaDataService 接口为 Heimdall 框架提供系统权限和用户权限数据。

系统权限规定了系统内哪些资源要进行权限管理。

用户权限规定了当前用户具备哪些系统权限。

实现如下:


/**
 * 权限数据提供服务
 *
 * @author Luter
 */
@Service
@Slf4j
public class AuthorizationMetaDataServiceImpl implements AuthorizationMetaDataService {
    /**
     * The Sys resource service.
     */
    @Autowired
    private SysResourceService sysResourceService;
    /**
     * The Sys user service.
     */
    @Autowired
    private SysUserService sysUserService;

    @Override
    public Map<String, Collection<String>> loadSysAuthorities() {
        final List<SysResourceDTO> objects = sysResourceService.listAll();
        if (null != objects && !objects.isEmpty()) {
            Map<String, Collection<String>> perms = new LinkedHashMap<>();
            for (SysResourceDTO resource : objects) {
                perms.put(resource.getUrl(), null);
            }
            log.warn("加载到的系统权限: \n{}", JacksonUtils.toPrettyJson(perms));
            return perms;
        }
        return new LinkedHashMap<>();
    }

    @Override
    public List<? extends GrantedAuthority> loadUserAuthorities(SimpleSession session) {
        final AppUserDetails details = (AppUserDetails) session.getDetails();
        final SysUserDTO user = details.getUser();
        final SysUserDTO theUser = sysUserService.getById(user.getId());
        final List<SysRoleDTO> roles = theUser.getRoles();
        //通过用户角色获取用户权限,去重
        if (null != roles && !roles.isEmpty()) {
            List<SysResourceDTO> all = new ArrayList<>();
            for (SysRoleDTO role : roles) {
                if (null != role.getResources() && !role.getResources().isEmpty()) {
                    all.addAll(role.getResources());
                }
            }
            final ArrayList<SysResourceDTO> userResources = all.stream().collect(collectingAndThen(toCollection(()
                    -> new TreeSet<>(comparing(SysResourceDTO::getId))), ArrayList::new));
            //构造权限缓存信息
            return userResources.stream().map(d -> new MethodAndUrlGrantedAuthority(d.getMethod(), d.getUrl())).collect(Collectors.toList());
        }

        return new ArrayList<>();
    }
}

在系统资源服务中添加获取全部系统权限的方法以及实现:

List<SysResourceDTO> listAll();
 @Override
    public List<SysResourceDTO> listAll() {
        final List<SysResourceEntity> all = sysResourceRepository.findAll();
        return sysResourceMapper.entityListToDTOList(all);
    }

# Heimdall 安全配置

新建 HeimdallConfig配置,内容如下:


/**
 * Heimdall 安全配置
 *
 * @author Luter
 */
@Configuration
@Slf4j
public class HeimdallConfig {
    /**
     * SessionDao 配置
     *
     * @param servletHolder the servlet holder
     * @return the session dao
     */
    @Bean
    public SessionDAO sessionDAO(ServletHolder servletHolder) {
        log.warn("初始化 SessionDAO");
        return new CaffeineSessionDaoImpl(servletHolder);
    }

    /**
     * 认证管理器
     *
     * @param sessionDAO the session dao
     * @return the authentication manager
     */
    @Bean
    public AuthenticationManager authenticationManager(SessionDAO sessionDAO) {
        log.warn("初始化 认证管理器");
        return new AuthenticationManager(sessionDAO);
    }

    /**
     * 权限缓存Dao,注册此 Bean 便于进行动态授权
     *
     * @return the authorization meta data cache dao
     */
    @Bean
    public AuthorizationMetaDataCacheDao authorizationMetaDataCacheDao() {
        log.warn("初始化 系统权限数据 MetaDataDao");
        return new CaffeineAuthorizationMetaDataDao();
    }

    /**
     * 授权管理器
     *
     * @param authenticationManager        the authentication manager
     * @param authorizationMetaDataService the authorization meta data service
     * @return the authorization manager
     */
    @Bean
    public AuthorizationManager authorizationManager(AuthenticationManager authenticationManager
            , AuthorizationMetaDataService authorizationMetaDataService, AuthorizationMetaDataCacheDao authorizationMetaDataCacheDao) {
        log.warn("初始化 授权管理器");
        return new AuthorizationManager(authorizationMetaDataService,
                authorizationMetaDataCacheDao, authenticationManager);
    }
}

至此,Heimdall 权限管理配置完毕。此时访问资源端点:/pet/cats ,将会提示需要登录。

下章开始,我们将实现登录、注销、在线用户管理等功能。

上次更新:: 1/25/2021, 4:26:40 PM