设为首页 收藏本站
查看: 758|回复: 0

[经验分享] tomcat 下软连接 freemark 模板文件不能访问

[复制链接]

尚未签到

发表于 2017-2-7 06:56:37 | 显示全部楼层 |阅读模式
环境:spring mvc +freemark 。模板由另一个项目生成。利用linux 的ln -s 软连接到webapp下

错误java.lang.SecurityException  

1.tomcat默认是不允许在webapp下用软连接文件夹的。

          需要在context.xml中配置 allowLinking="true"修改之后问题依旧。

2.仔细观察错误。好像是查找模板问题。查找模板嘛肯定是 temploader,有很多实现


  • ClassTemplateLoader
  • FileTemplateLoader
  • MultiTemplateLoader
  • StringTemplateLoader
  • URLTemplateLoader
  • WebappTemplateLoader


为什么用FileTemplateLoader 因为我的FreeMarkerConfigurer配置如下:



<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/pages/" />
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">0</prop>
<prop key="default_encoding">UTF-8</prop>
<prop key="number_format">0.##########</prop>
<prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
<prop key="classic_compatible">true</prop>
<prop key="template_exception_handler">ignore</prop>
</props>
</property>
</bean>



请注意templateLoaderPath。而在FreeMarkerConfigurer的父类FreeMarkerConfigurationFactorycreateConfiguration 方法中有这样一段


        
        // Register default template loaders.
if (this.templateLoaderPaths != null) {
for (String path : this.templateLoaderPaths) {
this.templateLoaders.add(getTemplateLoaderForPath(path));
}
}
 


getTemplateLoaderForPath这个方法的实现如下

protected TemplateLoader getTemplateLoaderForPath(String templateLoaderPath) {
if (isPreferFileSystemAccess()) {
// Try to load via the file system, fall back to SpringTemplateLoader
// (for hot detection of template changes, if possible).
try {
Resource path = getResourceLoader().getResource(templateLoaderPath);
File file = path.getFile();  // will fail if not resolvable in the file system
if (logger.isDebugEnabled()) {
logger.debug(
"Template loader path [" + path + "] resolved to file path [" + file.getAbsolutePath() + "]");
}
return new FileTemplateLoader(file);
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Cannot resolve template loader path [" + templateLoaderPath +
"] to [java.io.File]: using SpringTemplateLoader as fallback", ex);
}
return new SpringTemplateLoader(getResourceLoader(), templateLoaderPath);
}
}
else {
// Always load via SpringTemplateLoader (without hot detection of template changes).
logger.debug("File system access not preferred: using SpringTemplateLoader");
return new SpringTemplateLoader(getResourceLoader(), templateLoaderPath);
}
}
 

 

查看freemarker的 FileTemplateLoader原来做了检查,就是下面的红色部分

 
// Security check for inadvertently returning something
// outside the template directory when linking is not
// allowed.
if(canonicalPath != null) {
String normalized = source.getCanonicalPath();
if (!normalized.startsWith(canonicalPath)) {
throw new SecurityException(source.getAbsolutePath() + " resolves to " + normalized + " which " +
" doesn't start with " + canonicalPath);
}
}
 


解决方法:

1.修改源码------哈哈

2.忽然发现有一个构造方法是允许软连接的public FileTemplateLoader(final File baseDir, final boolean allowLinking)

所以想到用spring注入一个allowLinking =true的FileTemplateLoader。当我看到上面getTemplateLoaderForPath这个方法中的new FileTemplateLoader(file);这句话时.我尿了。这尼玛真是个坑13.不过springmvc提供了一个preferFileSystemAccess 意思是你是否喜欢FileTemplateLoader。不喜欢的用我的SpringTemplateLoader 吧。经测试这条路走不通,spring 也判断了真实路径。

3.看源码时看到支持templateLoaderPaths 注意多了一个s。多个路径。好吧。大家应该知道怎么办。

4.自定义Temploader你可以在配置FreeMarkerConfigurer时添加一个自己的preTemplateLoaders 或者postTemplateLoaders

这个很明显是前后。为什么提供前后。因为还有中间。哈哈。中间是谁。就是根据templateLoaderPath获取的。哈哈。好吧真213.

如果有多个到底用哪个呢 ?看看 createConfiguration这个方法中有这么一句

TemplateLoader loader = getAggregateTemplateLoader(this.templateLoaders);
protected TemplateLoader getAggregateTemplateLoader(List<TemplateLoader> templateLoaders) {
int loaderCount = templateLoaders.size();
switch (loaderCount) {
case 0:
logger.info("No FreeMarker TemplateLoaders specified");
return null;
case 1:
return templateLoaders.get(0);
default:
TemplateLoader[] loaders = templateLoaders.toArray(new TemplateLoader[loaderCount]);
return new MultiTemplateLoader(loaders);
}
}
 

那么会生成一个MultiTemplateLoader 哈哈。这货是按照顺序来的。代码很短。贴上来看看

 
public Object findTemplateSource(String name) throws IOException{
// Use soft affinity - give the loader that last found this
// resource a chance to find it again first.
TemplateLoader lastLoader = (TemplateLoader)lastLoaderForName.get(name);
if(lastLoader != null){
Object source = lastLoader.findTemplateSource(name);
if(source != null){
return new MultiSource(source, lastLoader);
}
}
// If there is no affine loader, or it could not find the resource
// again, try all loaders in order of appearance. If any manages
// to find the resource, then associate it as the new affine loader
// for this resource.
for(int i = 0; i < loaders.length; ++i){
TemplateLoader loader = loaders;
Object source = loader.findTemplateSource(name);
if(source != null){
lastLoaderForName.put(name, loader);
return new MultiSource(source, loader);
}
}
lastLoaderForName.remove(name);
// Resource not found
return null;
}
  


太明显不解释

当然你也可以不要中简单templateloader就是不定义templateLoaderPath属性。然后定义一个自己的templateloader注入到preTemplateLoaders 或者postTemplateL


5.好吧你可以更狠一点把FreeMarkerConfigurer也替换掉哈哈

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-338469-1-1.html 上篇帖子: 【责任链模式】Java版简单实例与Tomcat实例 下篇帖子: Xfire + JDK1.5 + MyEclipse + Tomcat 构建webservice服务
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表