001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.web.subject;
020
021 import org.apache.shiro.SecurityUtils;
022 import org.apache.shiro.mgt.SecurityManager;
023 import org.apache.shiro.subject.Subject;
024 import org.apache.shiro.subject.SubjectContext;
025 import org.apache.shiro.web.subject.support.DefaultWebSubjectContext;
026 import org.apache.shiro.web.util.RequestPairSource;
027
028 import javax.servlet.ServletRequest;
029 import javax.servlet.ServletResponse;
030
031 /**
032 * A {@code WebSubject} represents a Subject instance that was acquired as a result of an incoming
033 * {@link ServletRequest}.
034 *
035 * @since 1.0
036 */
037 public interface WebSubject extends Subject, RequestPairSource {
038
039 /**
040 * Returns the {@code ServletRequest} accessible when the Subject instance was created.
041 *
042 * @return the {@code ServletRequest} accessible when the Subject instance was created.
043 */
044 ServletRequest getServletRequest();
045
046 /**
047 * Returns the {@code ServletResponse} accessible when the Subject instance was created.
048 *
049 * @return the {@code ServletResponse} accessible when the Subject instance was created.
050 */
051 ServletResponse getServletResponse();
052
053 /**
054 * A {@code WebSubject.Builder} performs the same function as a {@link Subject.Builder Subject.Builder}, but
055 * additionally ensures that the Servlet request/response pair that is triggering the Subject instance's creation
056 * is retained for use by internal Shiro components as necessary.
057 */
058 public static class Builder extends Subject.Builder {
059
060 /**
061 * Constructs a new {@code Web.Builder} instance using the {@link SecurityManager SecurityManager} obtained by
062 * calling {@code SecurityUtils.}{@link SecurityUtils#getSecurityManager() getSecurityManager()}. If you want
063 * to specify your own SecurityManager instance, use the
064 * {@link #Builder(SecurityManager, ServletRequest, ServletResponse)} constructor instead.
065 *
066 * @param request the incoming ServletRequest that will be associated with the built {@code WebSubject} instance.
067 * @param response the outgoing ServletRequest paired with the ServletRequest that will be associated with the
068 * built {@code WebSubject} instance.
069 */
070 public Builder(ServletRequest request, ServletResponse response) {
071 this(SecurityUtils.getSecurityManager(), request, response);
072 }
073
074 /**
075 * Constructs a new {@code Web.Builder} instance using the specified {@code SecurityManager} instance to
076 * create the {@link WebSubject WebSubject} instance.
077 *
078 * @param securityManager the {@code SecurityManager SecurityManager} instance to use to build the
079 * {@code WebSubject} instance.
080 * @param request the incoming ServletRequest that will be associated with the built {@code WebSubject}
081 * instance.
082 * @param response the outgoing ServletRequest paired with the ServletRequest that will be associated
083 * with the built {@code WebSubject} instance.
084 */
085 public Builder(SecurityManager securityManager, ServletRequest request, ServletResponse response) {
086 super(securityManager);
087 if (request == null) {
088 throw new IllegalArgumentException("ServletRequest argument cannot be null.");
089 }
090 if (response == null) {
091 throw new IllegalArgumentException("ServletResponse argument cannot be null.");
092 }
093 setRequest(request);
094 setResponse(response);
095 }
096
097 /**
098 * Overrides the parent implementation to return a new instance of a
099 * {@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 }