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