Why doesn't Shiro's AnonymousFilter create new web sessions in this example?
我有两个受Shiro保护的应用程序,允许匿名访问所有页面。一个是部署在Jetty服务器内部的WAR,另一个是带有嵌入式Jetty服务器的独立Java应用程序。
战争应用
WEB-INF / shiro.ini:
1 2 3 4 5 6 | [main] sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager securityManager.sessionManager = $sessionManager [urls] /** = anon |
WEB-INF / web.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener> <filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping> <welcome-file-list> <welcome-file>home.jsp</welcome-file> </welcome-file-list> </web-app> |
home.jsp:
1 2 3 4 5 | <!DOCTYPE html> <html> <body> </body> </html> |
pom.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <?xml version="1.0" encoding="UTF-8"?> <!--suppress osmorcNonOsgiMavenDependency --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.foo.example</groupId> apache-shiro-tutorial-webapp</artifactId> <version>1.0.0-SNAPSHOT</version> <name>Apache Shiro Tutorial Webapp</name> <packaging>war</packaging> <build> <plugins> <plugin> <groupId>org.eclipse.jetty</groupId> jetty-maven-plugin</artifactId> <version>9.1.0.v20131115</version> <configuration> <webApp> <contextPath>/</contextPath> </webApp> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.apache.shiro</groupId> shiro-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> shiro-web</artifactId> <version>1.2.2</version> </dependency> </dependencies> </project> |
独立应用
classpath:shiro.ini:
1 2 3 4 5 6 | [main] sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager securityManager.sessionManager = $sessionManager [urls] /** = anon |
Main.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | import org.apache.shiro.SecurityUtils; import org.apache.shiro.web.env.EnvironmentLoaderListener; import org.apache.shiro.web.servlet.ShiroFilter; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import javax.servlet.DispatcherType; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import static java.util.EnumSet.allOf; public class Main { public static void main(String[] args) throws Exception { Server server = new Server(8080); ShiroFilter shiroFilter = new ShiroFilter(); ServletContextHandler context = new ServletContextHandler(); context.addEventListener(new EnvironmentLoaderListener()); context.setContextPath("/"); context.addFilter(new FilterHolder(shiroFilter),"/", allOf(DispatcherType.class)); context.addServlet(new ServletHolder(dummyServlet),"/"); server.setHandler(context); server.start(); SecurityUtils.setSecurityManager(shiroFilter.getSecurityManager()); server.join(); } private static HttpServlet dummyServlet = new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("OK"); } }; } |
pom.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>test</groupId> test</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.eclipse.jetty</groupId> jetty-server</artifactId> <version>9.3.1.v20150714</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> jetty-servlet</artifactId> <version>9.3.1.v20150714</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> shiro-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> shiro-web</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> slf4j-api</artifactId> <version>1.7.5</version> </dependency> <dependency> <groupId>org.slf4j</groupId> jcl-over-slf4j</artifactId> <version>1.7.5</version> <scope>runtime</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> logback-classic</artifactId> <version>1.0.13</version> <scope>runtime</scope> </dependency> </dependencies> </project> |
证明独立应用程序有效(因此,AnonymousFilter是问题所在)
在独立应用程序中,如果我将shiro.ini文件替换为:
1 2 3 4 5 6 7 8 9 | [main] sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager securityManager.sessionManager = $sessionManager [users] name = password [urls] /** = authcBasic |
然后我可以以"名称"身份登录并创建一个会话。似乎只有匿名过滤器拒绝创建会话。
其他资讯
当我说"创建会话"时,是指当我浏览到localhost:8080 /时,我可以在服务器的响应中看到
默认情况下,在Web应用程序中,Shiro将会话创建委托给容器:
来自http://shiro.apache.org/web.html#Web-SessionManagement:
In web environments, Shiro's default session manager SessionManager implementation is the ServletContainerSessionManager. This very simple implementation delegates all session management duties (including session clustering if the servlet container supports it) to the runtime Servlet container. It is essentially a bridge for Shiro's session API to the servlet container and does little else.
运行独立应用程序时,可以通过调用
BasicAuth的实现可能是隐式执行的,
使用anon时,请尝试在代码中使用
我已将此问题的原因归结为过滤器的url模式:
1 | /* |
vs
1 | / |