今天做了个上传文件功能的雏形,发现上传后的文件(URI)不受Grails的过滤器控制,用户不登陆也可以访问到这些资源,这自然就不安全咯。
开始还以为是uri匹配的不对,后来查阅文档才明白,Grails的过滤器只对controller有效,对静态资源无能为力(包括网站的各种图标)
[quote]Static resources aren't served by a controller, so Grails filters (which are wrappers for Spring controller interceptors) won't fire for requests for them. [/quote]
[b]解决办法,回归原本[/b]
[color=blue]1. 在src/java或src/groovy下创建一个过滤器,可以让它什么都不做[/color]
package myoa
import javax.servlet.*
class StaticFilter [color=red]implements Filter[/color] {
@Override
void init(FilterConfig filterConfig) {
println('StaticFilter init')
}
@Override
void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
println('StaticFilter doFilter')
}
@Override
void destroy() {
println('StaticFilter destroy')
}
}
[color=blue]2. 创建配置文件
grails install-templates
编辑之
src/templates/war/web.xml[/color]
<filter>
<filter-name>staticFilters</filter-name>
<filter-class>[color=red]myoa.StaticFilter[/color]</filter-class>
</filter>
<filter-mapping>
<filter-name>staticFilters</filter-name>
<url-pattern>[color=red]/file-store/*[/color]</url-pattern>
</filter-mapping>
这样就做好了一个最简单的静态资源过滤器,uri在file-store文件夹的所有资源将被禁止访问。
3. 再进一步,可以完善这个doFilter功能,其实这就是Grails的过滤器的本质。 [color=violet]这里倒是有了个小心得,越本质的东西,看起来复杂,理解起来容易(好比是Servlet);封装过的东西,用起来简单,理解起来困难(好比是Grails)。所以要两者兼顾,先实用主义,把东西先做出来,然后慢慢体会最本质的东西,好歹现在都是open source的,看源码比看文档来得更透彻。[/color]
void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) {
println('StaticFilter doFilter')
HttpServletRequest request = (HttpServletRequest) servletRequest
HttpServletResponse response = (HttpServletResponse) servletResponse
HttpSession session = request.getSession(false) //若存在会话则返回该会话,否则返回NULL
if (session?.getAttribute('loginUser')) {
chain.doFilter(servletRequest, servletResponse);//放行。让其走到下个链或目标资源中
} else {
println('please login')
response.sendRedirect(request.getContextPath() + "/user/login")
}
}
====有待研究====
staticFilter无效
<g:link url="${resource(dir: 'download', file: 'expense-this-month.xls')}">
http://localhost:8080/myoa/static/download/expense-multi-month.xls
staticFilter有效
<g:link uri='/download/expense-this-month.xls'>
http://localhost:8080/myoa/download/expense-multi-month.xls
开始还以为是uri匹配的不对,后来查阅文档才明白,Grails的过滤器只对controller有效,对静态资源无能为力(包括网站的各种图标)
[quote]Static resources aren't served by a controller, so Grails filters (which are wrappers for Spring controller interceptors) won't fire for requests for them. [/quote]
[b]解决办法,回归原本[/b]
[color=blue]1. 在src/java或src/groovy下创建一个过滤器,可以让它什么都不做[/color]
package myoa
import javax.servlet.*
class StaticFilter [color=red]implements Filter[/color] {
@Override
void init(FilterConfig filterConfig) {
println('StaticFilter init')
}
@Override
void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
println('StaticFilter doFilter')
}
@Override
void destroy() {
println('StaticFilter destroy')
}
}
[color=blue]2. 创建配置文件
grails install-templates
编辑之
src/templates/war/web.xml[/color]
<filter>
<filter-name>staticFilters</filter-name>
<filter-class>[color=red]myoa.StaticFilter[/color]</filter-class>
</filter>
<filter-mapping>
<filter-name>staticFilters</filter-name>
<url-pattern>[color=red]/file-store/*[/color]</url-pattern>
</filter-mapping>
这样就做好了一个最简单的静态资源过滤器,uri在file-store文件夹的所有资源将被禁止访问。
3. 再进一步,可以完善这个doFilter功能,其实这就是Grails的过滤器的本质。 [color=violet]这里倒是有了个小心得,越本质的东西,看起来复杂,理解起来容易(好比是Servlet);封装过的东西,用起来简单,理解起来困难(好比是Grails)。所以要两者兼顾,先实用主义,把东西先做出来,然后慢慢体会最本质的东西,好歹现在都是open source的,看源码比看文档来得更透彻。[/color]
void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) {
println('StaticFilter doFilter')
HttpServletRequest request = (HttpServletRequest) servletRequest
HttpServletResponse response = (HttpServletResponse) servletResponse
HttpSession session = request.getSession(false) //若存在会话则返回该会话,否则返回NULL
if (session?.getAttribute('loginUser')) {
chain.doFilter(servletRequest, servletResponse);//放行。让其走到下个链或目标资源中
} else {
println('please login')
response.sendRedirect(request.getContextPath() + "/user/login")
}
}
====有待研究====
staticFilter无效
<g:link url="${resource(dir: 'download', file: 'expense-this-month.xls')}">
http://localhost:8080/myoa/static/download/expense-multi-month.xls
staticFilter有效
<g:link uri='/download/expense-this-month.xls'>
http://localhost:8080/myoa/download/expense-multi-month.xls