关于java:在此示例中,为什么Shiro \\的AnonymousFilter不创建新的Web会话?

Why doesn't Shiro's AnonymousFilter create new web sessions in this example?

我有两个受Shiro保护的应用程序,允许匿名访问所有页面。一个是部署在Jetty服务器内部的WAR,另一个是带有嵌入式Jetty服务器的独立Java应用程序。

  • 为什么独立应用程序不创建会话,而WAR应用程序创建会话?
  • 如何配置独立应用程序以便创建会话?
  • 为什么独立应用程序需要在shiro.ini中显式定义会话管理器,而WAR应用程序却没有要求? (删除它意味着authcBasic过滤器也不起作用)。
  • 战争应用

    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 /时,我可以在服务器的响应中看到Set-Cookie: JSESSIONID=blahblahblah标头。独立应用程序中的匿名过滤器从未设置过此类cookie。


    默认情况下,在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.

    运行独立应用程序时,可以通过调用SecurityUtils.getSubject().getSession();(docu-link)来获取会话。
    BasicAuth的实现可能是隐式执行的,
    使用anon时,请尝试在代码中使用getSession()


    我已将此问题的原因归结为过滤器的url模式:

    1
    /*

    vs

    1
    /