Repository: wicket Updated Branches: refs/heads/master 98ffb2f6f -> 1c13446b7
Minor improvements to the security guide Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/1c13446b Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/1c13446b Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/1c13446b Branch: refs/heads/master Commit: 1c13446b71f1c51108c95274273a98e24b1d603d Parents: 98ffb2f Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Sun Aug 28 19:56:24 2016 +0200 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Sun Aug 28 19:56:24 2016 +0200 ---------------------------------------------------------------------- .../src/docs/guide/security/security_1.gdoc | 34 +++++++------------- .../src/docs/guide/security/security_2.gdoc | 30 ++++++++--------- .../src/docs/guide/security/security_3.gdoc | 20 ++++++------ .../src/docs/guide/security/security_4.gdoc | 13 +------- .../src/docs/guide/security/security_6.gdoc | 14 ++++---- 5 files changed, 45 insertions(+), 66 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/1c13446b/wicket-user-guide/src/docs/guide/security/security_1.gdoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/docs/guide/security/security_1.gdoc b/wicket-user-guide/src/docs/guide/security/security_1.gdoc index 4f1655c..66b39d3 100644 --- a/wicket-user-guide/src/docs/guide/security/security_1.gdoc +++ b/wicket-user-guide/src/docs/guide/security/security_1.gdoc @@ -13,12 +13,8 @@ Class AuthenticatedWebSession comes with the following set of public methods to * *authenticate(String username, String password)*: this is an abstract method that must be implemented by every subclass of @AuthenticatedWebSession@. It should contain the actual code that checks for user's identity. It returns a boolean value which is true if authentication has succeeded or false otherwise. * *signIn(String username, String password)*: this method internally calls authenticate and set the flag signedIn to true if authentication succeeds. * *isSignedIn()*:getter method for flag signedIn. -* *signOut()*: sets the flag signedIn to false. -* *invalidate()*: calls signOut and invalidates session. - -{warning} -Remember that signOut does not discard any session-relative data. If we want to get rid of these data, we must invoke method invalidate instead of signOut. -{warning} +* *invalidate()*: sets the flag signedIn to false and invalidates session. +* *signOut()*: an alias of *invalidate()*. Another abstract method we must implement when we use @AuthenticatedWebSession@ is getRoles which is inherited from parent class @AbstractAuthenticatedWebSession@. This method can be ignored for now as it will be discussed later when we will talk about role-based authorization. @@ -28,9 +24,9 @@ Class AuthenticatedWebApplication provides the following methods to support form * *getWebSessionClass()*: abstract method that returns the session class to use for this application. The returned class must be a subclass of @AbstractAuthenticatedWebSession@. * *getSignInPageClass()*: abstract method that returns the page to use as sign in page when a user must be authenticated. -* *restartResponseAtSignInPage()*: forces the current response to restart at the sign in page. After we have used this method to redirect a user, we can make her/him return to the original page calling @Componet@'s method @continueToOriginalDestination()@. +* *restartResponseAtSignInPage()*: forces the current response to restart at the sign in page. After we have used this method to redirect a user, we can make her/him return to the original page calling @Component@'s method @continueToOriginalDestination()@. -The other methods implemented inside @AuthenticatedWebApplication@ will be introduced when we will talk about authorizations. +The other methods implemented inside @AuthenticatedWebApplication@ will be introduced when we talk about authorization. h3. A basic example of authentication @@ -52,14 +48,8 @@ public class AuthenticatedPage extends WebPage { @Override protected void onInitialize() { super.onInitialize(); - add(new Link("goToHomePage") { + add(new BookmarkablePageLink("goToHomePage", getApplication().getHomePage())); - @Override - public void onClick() { - setResponsePage(getApplication().getHomePage()); - } - }); - add(new Link("logOut") { @Override @@ -85,7 +75,7 @@ public class SignInPage extends WebPage { protected void onInitialize() { super.onInitialize(); - StatelessForm form = new StatelessForm("form"){ + StatelessForm form = new StatelessForm("form") { @Override protected void onSubmit() { if(Strings.isEmpty(username)) @@ -98,7 +88,7 @@ public class SignInPage extends WebPage { } }; - form.setDefaultModel(new CompoundPropertyModel(this)); + form.setModel(new CompoundPropertyModel(this)); form.add(new TextField("username")); form.add(new PasswordTextField("password")); @@ -108,7 +98,7 @@ public class SignInPage extends WebPage { } {code} -The form is responsible for handling user authentication inside its method onSubmit. The username and password are passed to @AuthenticatedWebSession@'s method @signIn(username, password)@ and if authentication succeeds, the user is redirected to the original page with method @continueToOriginalDestination@. +The form is responsible for handling user authentication inside its method @onSubmit()@. The username and password are passed to @AuthenticatedWebSession@'s method @signIn(username, password)@ and if authentication succeeds, the user is redirected to the original page with method @continueToOriginalDestination@. The session class and the application class used in the project are reported here: @@ -118,7 +108,7 @@ The session class and the application class used in the project are reported her public class BasicAuthenticationSession extends AuthenticatedWebSession { public BasicAuthenticationSession(Request request) { - super(request); + super(request); } @Override @@ -129,7 +119,7 @@ public class BasicAuthenticationSession extends AuthenticatedWebSession { @Override public Roles getRoles() { - return null; + return new Roles(); } } {code} @@ -137,7 +127,7 @@ public class BasicAuthenticationSession extends AuthenticatedWebSession { *Application class:* {code} -public class WicketApplication extends AuthenticatedWebApplication{ +public class WicketApplication extends AuthenticatedWebApplication { @Override public Class<HomePage> getHomePage(){ return HomePage.class; @@ -159,7 +149,7 @@ The authentication logic inside authenticate has been kept quite trivial in orde h3. Redirecting user to an intermediate page -Method @restartResponseAtSignInPage@ is an example of redirecting user to an intermediate page before allowing him to access to the requested page. This method internally throws exception @org.apache.wicket.RestartResponseAtInterceptPageException@ which saves the URL of the requested page into session metadata and then redirects user to the page passed as constructor parameter (the sign in page). +Method @restartResponseAtSignInPage@ is an example of redirecting user to an intermediate page before allowing him to access to the requested page. This method internally throws exception @org.apache.wicket.RestartResponseAtInterceptPageException@ which saves the URL and the parameters of the requested page into session metadata and then redirects user to the page passed as constructor parameter (the sign in page). Component's method @redirectToInterceptPage(Page)@ works in much the same way as @restartResponseAtSignInPage@ but it allows us to specify which page to use as intermediate page: http://git-wip-us.apache.org/repos/asf/wicket/blob/1c13446b/wicket-user-guide/src/docs/guide/security/security_2.gdoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/docs/guide/security/security_2.gdoc b/wicket-user-guide/src/docs/guide/security/security_2.gdoc index 6739a72..08826f7 100644 --- a/wicket-user-guide/src/docs/guide/security/security_2.gdoc +++ b/wicket-user-guide/src/docs/guide/security/security_2.gdoc @@ -3,9 +3,9 @@ The authorization support provided by Wicket is built around the concept of authorization strategy which is represented by interface @IAuthorizationStrategy@ (in package @org.apache.wicket.authorization@): {code} -public interface IAuthorizationStrategy -{ - //interface methods +public interface IAuthorizationStrategy { + + //interface methods <T extends IRequestableComponent> boolean isInstantiationAuthorized(Class<T> componentClass); boolean isActionAuthorized(Component component, Action action); @@ -28,8 +28,8 @@ public interface IAuthorizationStrategy This interface defines two methods: -* isInstantiationAuthorized checks if user is allowed to instantiate a given component. -* isActionAuthorized checks if user is authorized to perform a given action on a component's instance. The standard actions checked by this method are defined into class Action and are Action.ENABLE and Action.RENDER. +* @isInstantiationAuthorized()@ checks if user is allowed to instantiate a given component. +* @isActionAuthorized()@ checks if user is authorized to perform a given action on a component's instance. The standard actions checked by this method are defined into class Action and are Action.ENABLE and Action.RENDER. Inside @IAuthorizationStrategy@ we can also find a default implementation of the interface (called ALLOW_ALL) that allows everyone to instantiate every component and perform every possible action on it. This is the default strategy adopted by class @Application@. @@ -42,8 +42,8 @@ To change the authorization strategy in use we must register the desired impleme { super.init(); getSecuritySettings(). - setAuthorizationStrategy(myAuthorizationStrategy); - } + setAuthorizationStrategy(myAuthorizationStrategy); + } //... {code} @@ -60,17 +60,17 @@ SimplePageAuthorizationStrategy authorizationStrategy = new SimplePageAuthorizat PageClassToCheck.class, SignInPage.class) { protected boolean isAuthorized() - { + { //Authentication code... } }; {code} -By default @SimplePageAuthorizationStrategy@ checks for permissions only on pages. If we want to change this behavior and check also other kinds of components, we must override method @isActionAuthorized@ and implement our custom logic inside it. +By default @SimplePageAuthorizationStrategy@ checks for permissions only on pages. If we want to change this behavior and check also other kinds of components, we must override method @isActionAuthorized()@ and implement our custom logic inside it. h3. Role-based strategies -At the end of [paragraph 22.1|guide:security_1] we have introduced AbstractAuthenticatedWebSession's method getRoles which is provided to support role-based authorization returning the set of roles granted to the current user. +At the end of [paragraph 22.1|guide:security_1] we have introduced AbstractAuthenticatedWebSession's method getRoles() which is provided to support role-based authorization returning the set of roles granted to the current user. In Wicket roles are simple strings like âBASIC_USERâ or âADMINâ (they don't need to be capitalized) and they are handled with class @org.apache.wicket.authroles.authorization.strategies.role.Roles@. This class extends standard HashSet collection adding some functionalities to check whether the set contains one or more roles. Class @Roles@ already defines roles Roles.USER and Roles.ADMIN. @@ -81,7 +81,7 @@ class BasicAuthenticationRolesSession extends AuthenticatedWebSession { private String userName; public BasicAuthenticationRolesSession(Request request) { - super(request); + super(request); } @Override @@ -130,7 +130,7 @@ The following code snippet reports both application and session classes from pro *Application class:* {code} -public class WicketApplication extends AuthenticatedWebApplication{ +public class WicketApplication extends AuthenticatedWebApplication { @Override public Class<? extends WebPage> getHomePage(){ return HomePage.class; @@ -196,11 +196,11 @@ public class BasicAuthenticationSession extends AuthenticatedWebSession { } {code} -The code that instantiates @MetaDataRoleAuthorizationStrategy@ and set it as application's strategy is inside application class method init. +The code that instantiates @MetaDataRoleAuthorizationStrategy@ and set it as application's strategy is inside application class method @init()@. Any subclass of @AbstractRoleAuthorizationStrategyWicket@ needs an implementation of interface @IRoleCheckingStrategy@ to be instantiated. For this purpose in the code above we used the application class itself because its base class @AuthenticatedWebApplication@ already implements interface @IRoleCheckingStrategy@. By default @AuthenticatedWebApplication@ checks for authorizations using the roles returned by the current @AbstractAuthenticatedWebSession@. As final step inside init we grant the access to page @AdminOnlyPage@ to ADMIN role calling method authorize. -The code from session class has three interesting methods. The first is authenticate which considers as valid credentials every pair of username and password having the same value. The second notable method is getRoles which returns role SIGNED_IN if user is authenticated and it adds role ADMIN if username is equal to superuser. Finally, we have method signOut which has been overridden in order to clean the username field used internally to generate roles. +The code from session class has three interesting methods. The first is @authenticate()@ which considers as valid credentials every pair of username and password having the same value. The second notable method is @getRoles()@ which returns role SIGNED_IN if user is authenticated and it adds role ADMIN if username is equal to superuser. Finally, we have method @signOut()@ which has been overridden in order to clean the username field used internally to generate roles. Now if we run the project and we try to access to @AdminOnlyPage@ from the home page without having the ADMIN role, we will be redirected to the default access-denied page used by Wicket: @@ -246,7 +246,7 @@ public class AdminOnlyPage extends WebPage { h3. Catching an unauthorized component instantiation -Interface IUnauthorizedComponentInstantiationListener (in package @org.apache.wicket.authorization@) is provided to give the chance to handle the case in which a user tries to instantiate a component without having the permissions to do it. The method defined inside this interface is @onUnauthorizedInstantiation(Component)@ and it is executed whenever a user attempts to execute an unauthorized instantiation. +Interface @IUnauthorizedComponentInstantiationListener@ (in package @org.apache.wicket.authorization@) is provided to give the chance to handle the case in which a user tries to instantiate a component without having the permissions to do it. The method defined inside this interface is @onUnauthorizedInstantiation(Component)@ and it is executed whenever a user attempts to execute an unauthorized instantiation. This listener must be registered into application's security settings with method @setUnauthorizedComponentInstantiationListener@ defined by setting class @SecuritySettings@. In the following code snippet we register a listener that redirect user to a warning page if he tries to do a not-allowed instantiation: http://git-wip-us.apache.org/repos/asf/wicket/blob/1c13446b/wicket-user-guide/src/docs/guide/security/security_3.gdoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/docs/guide/security/security_3.gdoc b/wicket-user-guide/src/docs/guide/security/security_3.gdoc index 26d58e3..42abbb4 100644 --- a/wicket-user-guide/src/docs/guide/security/security_3.gdoc +++ b/wicket-user-guide/src/docs/guide/security/security_3.gdoc @@ -2,24 +2,24 @@ HTTPS is the standard technology adopted on Internet to create a secure communication channel between web applications and their users. -In Wicket we can easily protect our pages with HTTPS mounting a special request mapper called @HttpsMapper@ and using annotation RequireHttps with those pages we want to serve over this protocol. Both these two entities are in package @org.apache.wicket.protocol.https@. +In Wicket we can easily protect our pages with HTTPS mounting a special request mapper called @HttpsMapper@ and using annotation @RequireHttps@ with those pages we want to serve over this protocol. Both these two entities are in package @org.apache.wicket.protocol.https@. -HttpsMapper wraps an existing mapper and redirects incoming requests to HTTPS if the related response must render a page containing annotation @RequireHttps@. Most of the times the wrapped mapper will be the root one, just like we saw before for @CryptoMapper@ in [paragraph 10.6|guide:urls_6]. +@HttpsMapper@ wraps an existing mapper and redirects incoming requests to HTTPS if the related response must render a page annotated with @RequireHttps@. Most of the times the wrapped mapper will be the root one, just like we saw before for @CryptoMapper@ in [paragraph 10.6|guide:urls_6]. -Another parameter needed to build a @HttpsMapper@ is an instance of class @HttpsConfi@g. This class allows us to specify which ports must be used for HTTPS and HTTP. By default the port numbers used by these two protocols are respectively 443 and 80. +Another parameter needed to build a @HttpsMapper@ is an instance of class @HttpsConfig@. This class allows us to specify which ports must be used for HTTPS and HTTP. By default the port numbers used by these two protocols are respectively 443 and 80. -The following code is taken from project @HttpsProtocolExample@ and illustrates how to enable HTTPS in our applications: +The following code is taken from project @HttpsProtocolExample@ and illustrates how to enable HTTPS in our applications: {code} //Application class code... @Override public void init(){ setRootRequestMapper(new HttpsMapper(getRootRequestMapper(), - new HttpsConfig(8080, 443))); + new HttpsConfig(8080, 8443))); } {code} -Now we can use annotation RequireHttps to specify which pages must be served using HTTPS: +Now we can use annotation @RequireHttps@ to specify which pages must be served using HTTPS: {code} @RequireHttps @@ -35,22 +35,22 @@ If we want to protect many pages with HTTPS without adding annotation @RequireHt {code} // Marker interface: @RequireHttps -public interface IMarker{ +public interface IMarker { } // Base class: @RequireHttps -public class BaseClass extends WebPage{ +public class BaseClass extends WebPage { //Page code... } // Secure page inheriting from BaseClass: -public class HttpsPage extends BaseClass{ +public class HttpsPage extends BaseClass { //Page code... } // Secure page implementing IMarker: -public class HttpsPage implements IMarker{ +public class HttpsPage implements IMarker { //Page code... } {code} http://git-wip-us.apache.org/repos/asf/wicket/blob/1c13446b/wicket-user-guide/src/docs/guide/security/security_4.gdoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/docs/guide/security/security_4.gdoc b/wicket-user-guide/src/docs/guide/security/security_4.gdoc index e4746ca..4251418 100644 --- a/wicket-user-guide/src/docs/guide/security/security_4.gdoc +++ b/wicket-user-guide/src/docs/guide/security/security_4.gdoc @@ -19,18 +19,7 @@ For better security it is recommended to install Java Cryptography Extension (JC By using @CryptoMapper(IRequestMapper wrappedMapper, Application application)@ constructor the mapper will use the configured @org.apache.wicket.util.crypt.ICryptFactory@ from @org.apache.wicket.settings.SecuritySettings#getCryptFactory()@. To use a stronger cryptography mechanism there are the following options: -* The first option is to use constructor @CryptoMapper(IRequestMapper wrappedMapper, IProvider<ICrypt> cryptProvider)@ and give it an implementation of @org.apache.wicket.util.IProvider@ that returns a custom @org.apache.wicket.util.crypt.ICrypt@. - -{note} [email protected]@ is a single-method interface that acts as object supplier: -{note} - -{code} -public interface IProvider<T> -{ - T get(); -} -{code} +* The first option is to use constructor @CryptoMapper(IRequestMapper wrappedMapper, Supplier<ICrypt> cryptProvider)@ and give it an implementation of @java.util.function.Supplier@ that returns a custom @org.apache.wicket.util.crypt.ICrypt@. * The second option is to register a cipher factory at application level with method @setCryptFactory(ICryptFactory cryptFactory)@ of class @SecuritySettings@: http://git-wip-us.apache.org/repos/asf/wicket/blob/1c13446b/wicket-user-guide/src/docs/guide/security/security_6.gdoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/docs/guide/security/security_6.gdoc b/wicket-user-guide/src/docs/guide/security/security_6.gdoc index bbb0316..392ed1c 100644 --- a/wicket-user-guide/src/docs/guide/security/security_6.gdoc +++ b/wicket-user-guide/src/docs/guide/security/security_6.gdoc @@ -13,12 +13,12 @@ protected void init() @Override public void onEndRequest(RequestCycle cycle) { - ((WebResponse)cycle.getResponse()).setHeader("X-XSS-Protection", "1; mode=block"); - ((WebResponse)cycle.getResponse()).setHeader("Strict-Transport-Security", "max-age=31536000;" - + " includeSubDomains; preload"); - ((WebResponse)cycle.getResponse()).setHeader("X-Content-Type-Options", "nosniff"); - ((WebResponse)cycle.getResponse()).setHeader("X-Frame-Options", "DENY"); - ((WebResponse)cycle.getResponse()).setHeader("Content-Security-Policy", "default-src https:"); + WebResponse response = (WebResponse) cycle.getResponse(); + response.setHeader("X-XSS-Protection", "1; mode=block"); + response.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload"); + response.setHeader("X-Content-Type-Options", "nosniff"); + response.setHeader("X-Frame-Options", "DENY"); + response.setHeader("Content-Security-Policy", "default-src https:"); } }); } @@ -38,4 +38,4 @@ Add this configuration to your web.xml (or let your server redirect to https): </security-constraint> {code} -After this changes you have to check if your web application continues to work because it fits the requirements given with this header files. For example that resources must not requested from other domains anymore. \ No newline at end of file +After this changes you have to check if your web application continues to work because it fits the requirements given with these headers. For example that resources could not be requested from other domains anymore.
