View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.web.subject;
20  
21  import org.apache.shiro.SecurityUtils;
22  import org.apache.shiro.mgt.SecurityManager;
23  import org.apache.shiro.subject.Subject;
24  import org.apache.shiro.subject.SubjectContext;
25  import org.apache.shiro.web.subject.support.DefaultWebSubjectContext;
26  import org.apache.shiro.web.util.RequestPairSource;
27  
28  import javax.servlet.ServletRequest;
29  import javax.servlet.ServletResponse;
30  
31  /**
32   * A {@code WebSubject} represents a Subject instance that was acquired as a result of an incoming
33   * {@link ServletRequest}.
34   *
35   * @since 1.0
36   */
37  public interface WebSubject extends Subject, RequestPairSource {
38  
39      /**
40       * Returns the {@code ServletRequest} accessible when the Subject instance was created.
41       *
42       * @return the {@code ServletRequest} accessible when the Subject instance was created.
43       */
44      ServletRequest getServletRequest();
45  
46      /**
47       * Returns the {@code ServletResponse} accessible when the Subject instance was created.
48       *
49       * @return the {@code ServletResponse} accessible when the Subject instance was created.
50       */
51      ServletResponse getServletResponse();
52  
53      /**
54       * A {@code WebSubject.Builder} performs the same function as a {@link Subject.Builder Subject.Builder}, but
55       * additionally ensures that the Servlet request/response pair that is triggering the Subject instance's creation
56       * is retained for use by internal Shiro components as necessary.
57       */
58      class Builder extends Subject.Builder {
59  
60          /**
61           * Constructs a new {@code Web.Builder} instance using the {@link SecurityManager SecurityManager} obtained by
62           * calling {@code SecurityUtils.}{@link SecurityUtils#getSecurityManager() getSecurityManager()}.  If you want
63           * to specify your own SecurityManager instance, use the
64           * {@link #Builder(SecurityManager, ServletRequest, ServletResponse)} constructor instead.
65           *
66           * @param request  the incoming ServletRequest that will be associated with the built {@code WebSubject} instance.
67           * @param response the outgoing ServletRequest paired with the ServletRequest that will be associated with the
68           *                 built {@code WebSubject} instance.
69           */
70          public Builder(ServletRequest request, ServletResponse response) {
71              this(SecurityUtils.getSecurityManager(), request, response);
72          }
73  
74          /**
75           * Constructs a new {@code Web.Builder} instance using the specified {@code SecurityManager} instance to
76           * create the {@link WebSubject WebSubject} instance.
77           *
78           * @param securityManager the {@code SecurityManager SecurityManager} instance to use to build the
79           *                        {@code WebSubject} instance.
80           * @param request         the incoming ServletRequest that will be associated with the built {@code WebSubject}
81           *                        instance.
82           * @param response        the outgoing ServletRequest paired with the ServletRequest that will be associated
83           *                        with the built {@code WebSubject} instance.
84           */
85          public Builder(SecurityManager securityManager, ServletRequest request, ServletResponse response) {
86              super(securityManager);
87              if (request == null) {
88                  throw new IllegalArgumentException("ServletRequest argument cannot be null.");
89              }
90              if (response == null) {
91                  throw new IllegalArgumentException("ServletResponse argument cannot be null.");
92              }
93              setRequest(request);
94              setResponse(response);
95          }
96  
97          /**
98           * Overrides the parent implementation to return a new instance of a
99           * {@link DefaultWebSubjectContext DefaultWebSubjectContext} to account for the additional request/response
100          * pair.
101          *
102          * @return a new instance of a {@link DefaultWebSubjectContext DefaultWebSubjectContext} to account for the
103          * additional request/response pair.
104          */
105         @Override
106         protected SubjectContext newSubjectContextInstance() {
107             return new DefaultWebSubjectContext();
108         }
109 
110         /**
111          * Called by the {@code WebSubject.Builder} constructor, this method places the request object in the
112          * context map for later retrieval.
113          *
114          * @param request the incoming ServletRequest that triggered the creation of the {@code WebSubject} instance.
115          * @return 'this' for method chaining.
116          */
117         protected Builder setRequest(ServletRequest request) {
118             if (request != null) {
119                 ((WebSubjectContext) getSubjectContext()).setServletRequest(request);
120             }
121             return this;
122         }
123 
124         /**
125          * Called by the {@code WebSubject.Builder} constructor, this method places the response object in the
126          * context map for later retrieval.
127          *
128          * @param response the outgoing ServletRequest paired with the ServletRequest that triggered the creation of
129          *                 the {@code WebSubject} instance.
130          * @return 'this' for method chaining.
131          */
132         protected Builder setResponse(ServletResponse response) {
133             if (response != null) {
134                 ((WebSubjectContext) getSubjectContext()).setServletResponse(response);
135             }
136             return this;
137         }
138 
139         /**
140          * Returns {@link #buildSubject() super.buildSubject()}, but additionally ensures that the returned instance
141          * is an {@code instanceof} {@link WebSubject WebSubject} and to support a type-safe method so a caller
142          * does not have to cast.   Per the parent class's method JavaDoc, this method will return a new instance
143          * each time it is called.
144          *
145          * @return a new {@link WebSubject WebSubject} instance built by this {@code Builder}.
146          */
147         public WebSubject buildWebSubject() {
148             Subject subject = super.buildSubject();
149             if (!(subject instanceof WebSubject)) {
150                 String msg = "Subject implementation returned from the SecurityManager was not a "
151                         + WebSubject.class.getName() + " implementation.  Please ensure a Web-enabled SecurityManager "
152                         + "has been configured and made available to this builder.";
153                 throw new IllegalStateException(msg);
154             }
155             return (WebSubject) subject;
156         }
157     }
158 
159 }