Shiro 3 shiroFilter

本文详细解析了ShiroFilterFactoryBean的配置方法及其内部工作流程。包括如何配置过滤器和URL权限映射,以及创建SpringShiroFilter的过程。

ShiroFilterFactoryBean中getObject()方法

  public Object getObject() throws Exception {
        if (instance == null) {
            instance = createInstance();
        }
        return instance;
    } 

protected AbstractShiroFilter createInstance() throws Exception {

        log.debug("Creating Shiro Filter instance.");

        SecurityManager securityManager = getSecurityManager();
        if (securityManager == null) {
            String msg = "SecurityManager property must be set.";
            throw new BeanInitializationException(msg);
        }

        if (!(securityManager instanceof WebSecurityManager)) {
            String msg = "The security manager does not implement the WebSecurityManager interface.";
            throw new BeanInitializationException(msg);
        }

        FilterChainManager manager = createFilterChainManager();//创建过滤器链管理器

        //Expose the constructed FilterChainManager by first wrapping it in a
        // FilterChainResolver implementation. The AbstractShiroFilter implementations
        // do not know about FilterChainManagers - only resolvers:
        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
        chainResolver.setFilterChainManager(manager);

        //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
        //FilterChainResolver.  It doesn't matter that the instance is an anonymous inner class
        //here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
        //injection of the SecurityManager and FilterChainResolver:
        return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
    }
 protected FilterChainManager createFilterChainManager() {

        DefaultFilterChainManager manager = new DefaultFilterChainManager();
        Map<String, Filter> defaultFilters = manager.getFilters();//1
        //apply global settings if necessary:
        for (Filter filter : defaultFilters.values()) {
            applyGlobalPropertiesIfNecessary(filter);
        }

        //Apply the acquired and/or configured filters:
        Map<String, Filter> filters = getFilters();
        if (!CollectionUtils.isEmpty(filters)) {//把配置的filter加入到manager的filteMap中
            for (Map.Entry<String, Filter> entry : filters.entrySet()) {
                String name = entry.getKey();
                Filter filter = entry.getValue();
                applyGlobalPropertiesIfNecessary(filter);
                if (filter instanceof Nameable) {
                    ((Nameable) filter).setName(name);
                }
                //'init' argument is false, since Spring-configured filters should be initialized
                //in Spring (i.e. 'init-method=blah') or implement InitializingBean:
                manager.addFilter(name, filter, false);
            }
        }

        //build up the chains:
        Map<String, String> chains = getFilterChainDefinitionMap();
        if (!CollectionUtils.isEmpty(chains)) {
            for (Map.Entry<String, String> entry : chains.entrySet()) {
                String url = entry.getKey();
                String chainDefinition = entry.getValue();
                manager.createChain(url, chainDefinition);//2
            }
        }

        return manager;
    }

 

//1

DefaultFilterChainManager manager = new DefaultFilterChainManager();

DefaultFilterChainManager中

 public DefaultFilterChainManager() {
        this.filters = new LinkedHashMap<String, Filter>();
        this.filterChains = new LinkedHashMap<String, NamedFilterList>();
        addDefaultFilters(false);
    }

 protected void addDefaultFilters(boolean init) {
        for (DefaultFilter defaultFilter : DefaultFilter.values()) {
            addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
        }
    }

public enum DefaultFilter {

    anon(AnonymousFilter.class),
    authc(FormAuthenticationFilter.class),
    authcBasic(BasicHttpAuthenticationFilter.class),
    logout(LogoutFilter.class),
    noSessionCreation(NoSessionCreationFilter.class),
    perms(PermissionsAuthorizationFilter.class),
    port(PortFilter.class),
    rest(HttpMethodPermissionFilter.class),
    roles(RolesAuthorizationFilter.class),
    ssl(SslFilter.class),
    user(UserFilter.class);

DefaultFilterChainManager为Map<String, Filter> filters添加了默认的过滤器

//2

加入配置的url的过滤器

 public void createChain(String chainName, String chainDefinition) {
        if (!StringUtils.hasText(chainName)) {
            throw new NullPointerException("chainName cannot be null or empty.");
        }
        if (!StringUtils.hasText(chainDefinition)) {
            throw new NullPointerException("chainDefinition cannot be null or empty.");
        }

        if (log.isDebugEnabled()) {
            log.debug("Creating chain [" + chainName + "] from String definition [" + chainDefinition + "]");
        }

        //parse the value by tokenizing it to get the resulting filter-specific config entries
        //
        //e.g. for a value of
        //
        //     "authc, roles[admin,user], perms[file:edit]"
        //
        // the resulting token array would equal
        //
        //     { "authc", "roles[admin,user]", "perms[file:edit]" }
        //
        String[] filterTokens = splitChainDefinition(chainDefinition);

        //each token is specific to each filter.
        //strip the name and extract any filter-specific config between brackets [ ]
        for (String token : filterTokens) {
            String[] nameConfigPair = toNameConfigPair(token);

            //now we have the filter name, path and (possibly null) path-specific config.  Let's apply them:
            addToChain(chainName, nameConfigPair[0], nameConfigPair[1]);//参数 url,roles,admin,user
        }
    }
 public void addToChain(String chainName, String filterName, String chainSpecificFilterConfig) {
        if (!StringUtils.hasText(chainName)) {
            throw new IllegalArgumentException("chainName cannot be null or empty.");
        }
        Filter filter = getFilter(filterName);
        if (filter == null) {
            throw new IllegalArgumentException("There is no filter with name '" + filterName +
                    "' to apply to chain [" + chainName + "] in the pool of available Filters.  Ensure a " +
                    "filter with that name/path has first been registered with the addFilter method(s).");
        }

        applyChainConfig(chainName, filter, chainSpecificFilterConfig);

        NamedFilterList chain = ensureChain(chainName);  //得到以url为key的过滤器列表,加入此过滤器
        chain.add(filter);
    }

    protected void applyChainConfig(String chainName, Filter filter, String chainSpecificFilterConfig) {
        if (log.isDebugEnabled()) {
            log.debug("Attempting to apply path [" + chainName + "] to filter [" + filter + "] " +
                    "with config [" + chainSpecificFilterConfig + "]");
        }
        if (filter instanceof PathConfigProcessor) {
            ((PathConfigProcessor) filter).processPathConfig(chainName, chainSpecificFilterConfig);
      //注意,设置了指定过滤器的Map<String, Object> appliedPaths key是url value是中括号里面的角色,权限名
        } else {
            if (StringUtils.hasText(chainSpecificFilterConfig)) {
                //they specified a filter configuration, but the Filter doesn't implement PathConfigProcessor
                //this is an erroneous config:
                String msg = "chainSpecificFilterConfig was specified, but the underlying " +
                        "Filter instance is not an 'instanceof' " +
                        PathConfigProcessor.class.getName() + ".  This is required if the filter is to accept " +
                        "chain-specific configuration.";
                throw new ConfigurationException(msg);
            }
        }
    }

接口

public interface PathConfigProcessor {

    /**
     * Processes the specified {@code config}, unique to the given {@code path}, and returns the Filter that should
     * execute for that path/config combination.
     *
     * @param path   the path for which the {@code config} should be applied
     * @param config the configuration for the {@code Filter} specific to the given {@code path}
     * @return the {@code Filter} that should execute for the given path/config combination.
     */
    Filter processPathConfig(String path, String config);
}

可以看到Shiro的web过滤器都实现了此接口


整个过程大致就是:

1、配置ShiroFilterFactoryBean的Map<String, Filter> filters 和 Map<String, String> filterChainDefinitionMap 和WebSecurityManager

2、创建SpringShiroFilter过滤器,这个过程需要PathMatchingFilterChainResolver和WebSecurityManager

3、创建 FilterChainManager manager,new出默认的DefaultFilterChainManager(Map<String, Filter> filters,Map<String, NamedFilterList> filterChains) 此过程会给

filters加入默认的过滤器,然后根据ShiroFilterFactoryBean的配置修改部分过滤器中的配置,比如loginurl等,

然后会将ShiroFilterFactoryBean中配置的过滤器filters也配置applyGlobalPropertiesIfNecessary  ,然后加入到 FilterChainManager的filters中,

接着会解析filterChainDefinitionMap中配置的url与权限的信息(xx.action = authc, roles[admin,user], perms[file:edit])

这个过程呢会创建一个NamedFilterList保存符合条件的过滤器 并将这个list放到filterChains中  key为url

而这个符合条件的过滤器就是根据authc或者roles或者其他你配置的过滤器名称,在filters中查找,并且每个过滤器还会去设置类似admin,user的属性,属性名称为

PathMatchingFilter中的Map<String, Object> appliedPaths

4、显然最后的过滤过程就是  SpringShiroFilter得到请求,然后使用FilterChainManager从filterChains中根据url查找过滤器list,创建新的过滤器链,执行过滤器链



<think>好的,用户想要了解如何从PPT或者有很多图片的PDF中提取文字。我需要先理清楚用户的需求,可能的场景,以及潜在的问题。首先,PPT图片型PDF中的文字通常是嵌入在图像中的,普通的复制粘贴方法不管用,必须用OCR(光学字符识别)技术。用户可能是个学生、教师,或者办公人员,需要处理课件、报告或者文档,想要提取里面的文字进行编辑或整理。 接下来,我需要考虑不同的解决方案,覆盖免费和付费工具,本地和在线服务,以及编程方法。常见的方法包括使用Adobe Acrobat这样的专业软件,或者免费的在线OCR网站。另外,手机应用也可能是一个方便的选择,特别是用微信QQ的扫描功能。对于技术背景的用户,可能需要提到Python库如PyMuPDF和Tesseract,或者开源工具如OCRmyPDF。 还要注意用户可能关心的问题,比如准确性、处理速度、隐私安全,尤其是处理敏感内容时在线工具的风险。此外,批量处理和大文件的支持也是需要考虑的点。需要提醒用户,如果排版复杂或图片质量差,OCR效果可能不佳,建议预处理图片。 然后,我应该分步骤介绍各种方案,从最简单易用的开始,逐步到更专业的工具。确保结构清晰,用户可以根据自己的需求选择合适的方法。最后总结关键点,帮助用户做出决策。检查是否有遗漏的工具或方法,确保信息准确,比如确认最新版的OneDrive和Google Drive是否支持OCR,以及常用软件是否有更新。</think>提取PPT图片型PDF中的文字,核心需依赖OCR(光学字符识别)技术。以下是分场景的解决方案: --- ### 一、**免费方案** 1. **Office自带功能** - **Word 2013+**:直接将PPT/PDF拖入Word,右键图片选「复制图片中的文本」 - **OneDrive网页版**:上传文件后右键选择「在Word中打开」,可提取图片文字 2. **微信/QQ快捷提取** - 手机截图后通过微信「扫一扫」或QQ「提取图中文字」功能识别 3. **在线OCR工具** - **iLovePDF** (https://www.ilovepdf.com/ocr-pdf):支持多语言,免费版有限额 - **Google Drive**:上传PDF→右键「用Google文档打开」自动OCR识别 --- ### 二、**专业软件方案** 1. **Adobe Acrobat Pro**(高精度首选) - 操作路径:工具→扫描和OCR→「识别文本」→选择输出格式 - 优势:支持批量处理、保留排版、多语言混合识别 2. **ABBYY FineReader**(学术场景推荐) - 特点:复杂表格/公式识别能力强,支持导出Markdown/Excel格式 --- ### 三、**编程实现(开发者适用)** ```python # 示例:Python + PyMuPDF + Tesseract import fitz # PyMuPDF import pytesseract from PIL import Image doc = fitz.open("input.pdf") for page in doc: pix = page.get_pixmap(dpi=200) # 设置分辨率 img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples) text = pytesseract.image_to_string(img, lang='chi_sim+eng') # 中英混合 print(text) ``` **依赖库安装**: ```bash pip install PyMuPDF pytesseract # 需额外安装Tesseract本体:https://github.com/UB-Mannheim/tesseract/wiki ``` --- ### 四、**开源工具推荐** - **OCRmyPDF** (命令行工具) ```bash ocrmypdf --output-type pdf --language chi_sim input.pdf output.pdf ``` - **Umi-OCR** (Windows GUI):支持离线批量处理(GitHub开源项目) --- ### **注意事项** 1. **精度提升技巧**: - 扫描文件建议预处理:PS/画图工具调整对比度>300dpi - 复杂排版优先用Adobe/ABBYY 2. **隐私保护**:敏感内容建议使用离线工具(如Umi-OCR) 3. **特殊内容**:手写体识别推荐「腾讯云OCR」或「百度文字识别」API 根据文件复杂度、预算和隐私需求选择方案,常规办公推荐组合:微信快速识别+Adobe处理专业文档。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值