001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.settings; 018 019import org.apache.wicket.Application; 020import org.apache.wicket.Component; 021import org.apache.wicket.authentication.IAuthenticationStrategy; 022import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy; 023import org.apache.wicket.authorization.IAuthorizationStrategy; 024import org.apache.wicket.authorization.IUnauthorizedComponentInstantiationListener; 025import org.apache.wicket.authorization.IUnauthorizedResourceRequestListener; 026import org.apache.wicket.authorization.UnauthorizedInstantiationException; 027import org.apache.wicket.coep.CrossOriginEmbedderPolicyConfiguration; 028import org.apache.wicket.coep.CrossOriginEmbedderPolicyConfiguration.CoepMode; 029import org.apache.wicket.coop.CrossOriginOpenerPolicyConfiguration; 030import org.apache.wicket.coop.CrossOriginOpenerPolicyConfiguration.CoopMode; 031import org.apache.wicket.core.random.DefaultSecureRandomSupplier; 032import org.apache.wicket.core.random.ISecureRandomSupplier; 033import org.apache.wicket.core.util.crypt.KeyInSessionSunJceCryptFactory; 034import org.apache.wicket.util.crypt.ICryptFactory; 035import org.apache.wicket.util.lang.Args; 036 037/** 038 * Class for security related settings 039 * 040 * @author Jonathan Locke 041 * @author Chris Turner 042 * @author Eelco Hillenius 043 * @author Juergen Donnerstag 044 * @author Johan Compagner 045 * @author Igor Vaynberg (ivaynberg) 046 * @author Martijn Dashorst 047 * @author James Carman 048 */ 049public class SecuritySettings 050{ 051 /** 052 * encryption key is no longer used 053 * 054 * @deprecated 055 */ 056 @Deprecated(forRemoval = true) 057 public static final String DEFAULT_ENCRYPTION_KEY = "WiCkEt-FRAMEwork"; 058 059 /** The authorization strategy. */ 060 private IAuthorizationStrategy authorizationStrategy = IAuthorizationStrategy.ALLOW_ALL; 061 062 /** The authentication strategy. */ 063 private IAuthenticationStrategy authenticationStrategy; 064 065 /** factory for creating crypt objects */ 066 private ICryptFactory cryptFactory; 067 068 /** supplier of random data and SecureRandom */ 069 private ISecureRandomSupplier randomSupplier = new DefaultSecureRandomSupplier(); 070 071 /** 072 * Whether mounts should be enforced. If {@code true}, requests for a page will be 073 * allowed only if the page has been explicitly mounted in {@link Application#init() MyApplication#init()}. 074 * 075 * This setting basically disables {@link org.apache.wicket.core.request.mapper.BookmarkableMapper} 076 */ 077 private boolean enforceMounts = false; 078 079 /** 080 * Represents the configuration for Cross-Origin-Opener-Policy headers 081 */ 082 private CrossOriginOpenerPolicyConfiguration crossOriginOpenerPolicyConfiguration = new CrossOriginOpenerPolicyConfiguration( 083 CoopMode.SAME_ORIGIN); 084 085 /** 086 * Represents the configuration for Cross-Origin-Embedder-Policy headers 087 */ 088 private CrossOriginEmbedderPolicyConfiguration crossOriginEmbedderPolicyConfiguration = new CrossOriginEmbedderPolicyConfiguration( 089 CoepMode.REPORTING); 090 091 /** Authorizer for component instantiations */ 092 private static final IUnauthorizedComponentInstantiationListener DEFAULT_UNAUTHORIZED_COMPONENT_INSTANTIATION_LISTENER = new IUnauthorizedComponentInstantiationListener() 093 { 094 /** 095 * Called when an unauthorized component instantiation is about to take place (but before it 096 * happens). 097 * 098 * @param component 099 * The partially constructed component (only the id is guaranteed to be valid). 100 */ 101 @Override 102 public void onUnauthorizedInstantiation(final Component component) 103 { 104 throw new UnauthorizedInstantiationException(component.getClass()); 105 } 106 }; 107 108 private IUnauthorizedComponentInstantiationListener unauthorizedComponentInstantiationListener = 109 DEFAULT_UNAUTHORIZED_COMPONENT_INSTANTIATION_LISTENER; 110 111 private static final IUnauthorizedResourceRequestListener DEFAULT_UNAUTHORIZED_RESOURCE_REQUEST_LISTENER = 112 new DefaultUnauthorizedResourceRequestListener(); 113 114 private IUnauthorizedResourceRequestListener unauthorizedResourceRequestListener = DEFAULT_UNAUTHORIZED_RESOURCE_REQUEST_LISTENER; 115 116 /** 117 * Gets the authorization strategy. 118 * 119 * @return Returns the authorizationStrategy. 120 */ 121 public IAuthorizationStrategy getAuthorizationStrategy() 122 { 123 return authorizationStrategy; 124 } 125 126 /** 127 * Returns the {@link ICryptFactory}. If no factory is set, a {@link KeyInSessionSunJceCryptFactory} 128 * is used. 129 * 130 * @return crypt factory used to generate crypt objects 131 */ 132 public synchronized ICryptFactory getCryptFactory() 133 { 134 if (cryptFactory == null) 135 { 136 cryptFactory = new KeyInSessionSunJceCryptFactory(); 137 } 138 return cryptFactory; 139 } 140 141 /** 142 * Returns the {@link ISecureRandomSupplier} to use for secure random data. If no custom 143 * supplier is set, a {@link DefaultSecureRandomSupplier} is used. 144 * 145 * @return The {@link ISecureRandomSupplier} to use for secure random data. 146 */ 147 public ISecureRandomSupplier getRandomSupplier() 148 { 149 return randomSupplier; 150 } 151 152 /** 153 * Gets whether page mounts should be enforced. If {@code true}, requests for a page will be 154 * allowed only if the page has been explicitly mounted in {@link Application#init() MyApplication#init()}. 155 * 156 * This setting basically disables {@link org.apache.wicket.core.request.mapper.BookmarkableMapper} 157 * 158 * @return Whether mounts should be enforced 159 */ 160 public boolean getEnforceMounts() 161 { 162 return enforceMounts; 163 } 164 165 /** 166 * @return The listener 167 * @see IUnauthorizedComponentInstantiationListener 168 */ 169 public IUnauthorizedComponentInstantiationListener getUnauthorizedComponentInstantiationListener() 170 { 171 return unauthorizedComponentInstantiationListener; 172 } 173 174 /** 175 * Sets the authorization strategy. 176 * 177 * @param strategy 178 * new authorization strategy 179 * @return {@code this} object for chaining 180 */ 181 public SecuritySettings setAuthorizationStrategy(IAuthorizationStrategy strategy) 182 { 183 Args.notNull(strategy, "strategy"); 184 authorizationStrategy = strategy; 185 return this; 186 } 187 188 /** 189 * Sets the factory that will be used to create crypt objects. The crypt object returned from 190 * the first call is cached. 191 * 192 * @param cryptFactory 193 * @return {@code this} object for chaining 194 */ 195 public SecuritySettings setCryptFactory(ICryptFactory cryptFactory) 196 { 197 Args.notNull(cryptFactory, "cryptFactory"); 198 this.cryptFactory = cryptFactory; 199 return this; 200 } 201 202 /** 203 * Sets the supplier of secure random data for Wicket. The implementation must use a strong 204 * source of random data and be able to generate a lot of random data without running out of 205 * entropy. 206 * 207 * @param randomSupplier 208 * The new supplier, must not be null. 209 * @return {@code this} object for chaining 210 */ 211 public SecuritySettings setRandomSupplier(ISecureRandomSupplier randomSupplier) 212 { 213 Args.notNull(randomSupplier, "randomSupplier"); 214 this.randomSupplier = randomSupplier; 215 return this; 216 } 217 218 /** 219 * Sets whether mounts should be enforced. If true, requests for mounted targets have to done 220 * through the mounted paths. If, for instance, a bookmarkable page is mounted to a path, a 221 * request to that same page via the bookmarkablePage parameter will be denied. 222 * 223 * @param enforce 224 * Whether mounts should be enforced 225 * @return {@code this} object for chaining 226 */ 227 public SecuritySettings setEnforceMounts(boolean enforce) 228 { 229 enforceMounts = enforce; 230 return this; 231 } 232 233 /** 234 * @param listener 235 * The listener to set 236 * @see IUnauthorizedComponentInstantiationListener 237 * @return {@code this} object for chaining 238 */ 239 public SecuritySettings setUnauthorizedComponentInstantiationListener( 240 IUnauthorizedComponentInstantiationListener listener) 241 { 242 this.unauthorizedComponentInstantiationListener = listener == null ? 243 DEFAULT_UNAUTHORIZED_COMPONENT_INSTANTIATION_LISTENER : 244 listener; 245 return this; 246 } 247 248 /** 249 * @return The listener that will be used when a request to an IResource is not allowed for some reason 250 */ 251 public IUnauthorizedResourceRequestListener getUnauthorizedResourceRequestListener() 252 { 253 return unauthorizedResourceRequestListener; 254 } 255 256 /** 257 * Sets a listener that will be used when a request to an IResource is not allowed for some reason 258 * 259 * @param listener 260 * The listener 261 * @return {@code this} object for chaining 262 */ 263 public SecuritySettings setUnauthorizedResourceRequestListener(IUnauthorizedResourceRequestListener listener) 264 { 265 this.unauthorizedResourceRequestListener = listener == null ? 266 DEFAULT_UNAUTHORIZED_RESOURCE_REQUEST_LISTENER : 267 listener; 268 return this; 269 } 270 271 /** 272 * Gets the authentication strategy. 273 * 274 * @return Returns the authentication strategy. 275 */ 276 @SuppressWarnings("deprecation") 277 public IAuthenticationStrategy getAuthenticationStrategy() 278 { 279 if (authenticationStrategy == null) 280 { 281 authenticationStrategy = new DefaultAuthenticationStrategy("LoggedIn"); 282 } 283 return authenticationStrategy; 284 } 285 286 /** 287 * Sets the authentication strategy. 288 * 289 * @param strategy 290 * new authentication strategy 291 * @return {@code this} object for chaining 292 */ 293 public SecuritySettings setAuthenticationStrategy(final IAuthenticationStrategy strategy) 294 { 295 authenticationStrategy = strategy; 296 return this; 297 } 298 299 public CrossOriginOpenerPolicyConfiguration getCrossOriginOpenerPolicyConfiguration() 300 { 301 return crossOriginOpenerPolicyConfiguration; 302 } 303 304 /** 305 * Sets the Cross-Origin Opener Policy's mode and exempted paths. The config values are only 306 * read once at startup in Application#initApplication(), changing the config at runtime will have no effect 307 * 308 * @param mode 309 * CoopMode, one of the 4 values: UNSAFE_NONE, SAME_ORIGIN, SAME_ORIGIN_ALLOW_POPUPS, DISABLED 310 * @param exemptions 311 * exempted paths for which COOP will be disabled 312 * @return 313 */ 314 public SecuritySettings setCrossOriginOpenerPolicyConfiguration( 315 CoopMode mode, String... exemptions) 316 { 317 crossOriginOpenerPolicyConfiguration = new CrossOriginOpenerPolicyConfiguration(mode, exemptions); 318 return this; 319 } 320 321 322 public CrossOriginEmbedderPolicyConfiguration getCrossOriginEmbedderPolicyConfiguration() 323 { 324 return crossOriginEmbedderPolicyConfiguration; 325 } 326 327 /** 328 * Sets the Cross-Origin Embedder Policy's mode and exempted paths. The config values are only 329 * read once at startup in Application#initApplication(), changing the config at runtime will 330 * have no effect 331 * 332 * @param mode 333 * CoepMode, one of the 3 values: ENFORCING, REPORTING, DISABLED 334 * @param exemptions 335 * exempted paths for which COEP will be disabled 336 * @return 337 */ 338 public SecuritySettings setCrossOriginEmbedderPolicyConfiguration(CoepMode mode, 339 String... exemptions) 340 { 341 crossOriginEmbedderPolicyConfiguration = new CrossOriginEmbedderPolicyConfiguration(mode, 342 exemptions); 343 return this; 344 } 345 346}