Modified: websites/staging/deltaspike/trunk/content/documentation/security.html ============================================================================== --- websites/staging/deltaspike/trunk/content/documentation/security.html (original) +++ websites/staging/deltaspike/trunk/content/documentation/security.html Wed Feb 5 11:59:54 2020 @@ -1,829 +1,829 @@ -<!DOCTYPE html> -<head> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <meta name="description" content="deltaspike-generate-pages"> - <meta name="author" content="chm"> - <!-- No caching headers --> - <meta http-equiv="cache-control" content="no-cache"/> - <meta http-equiv="pragma" content="no-cache"/> - <meta http-equiv="expires" content="-1"/> - - <title>Security Module</title> - - <!-- - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - --> - - <!-- Styles --> - <link href="https://deltaspike.apache.org/resources/css/bootstrap.css" rel="stylesheet"> - <link href="https://deltaspike.apache.org/resources/css/bootstrap-responsive.css" rel="stylesheet"> - <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/3.1.0/css/font-awesome.min.css" rel="stylesheet"> - - - - - <!-- Tocify - nice dynamic autoscrolling TOC --> - <link href="https://cdnjs.cloudflare.com/ajax/libs/jquery.tocify/1.9.0/stylesheets/jquery.tocify.min.css" rel="stylesheet"> - <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.tocify/1.9.0/javascripts/jquery.tocify.min.js"></script> - - - <script type="text/javascript"> - $(function () { - $("#toc").tocify({ - scrollTo: 50, - extendPage: true, - context: "#doc-content", - selectors: "h2,h3,h4,h5" - }); - $(".fallback-toc").hide(); - }); - </script> - - - <style type="text/css"> - /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */ -/*pre.CodeRay {background-color:#f7f7f8;}*/ -.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em} -.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)} -.CodeRay .line-numbers strong{font-weight: normal} -table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none} -table.CodeRay td{vertical-align: top} -table.CodeRay td.line-numbers{text-align:right} -table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)} -table.CodeRay td.code{padding:0 0 0 .5em} -table.CodeRay td.code>pre{padding:0} -.CodeRay .debug{color:#fff !important;background:#000080 !important} -.CodeRay .annotation{color:#007} -.CodeRay .attribute-name{color:#000080} -.CodeRay .attribute-value{color:#700} -.CodeRay .binary{color:#509} -.CodeRay .comment{color:#998;font-style:italic} -.CodeRay .char{color:#04d} -.CodeRay .char .content{color:#04d} -.CodeRay .char .delimiter{color:#039} -.CodeRay .class{color:#458;font-weight:bold} -.CodeRay .complex{color:#a08} -.CodeRay .constant,.CodeRay .predefined-constant{color:#008080} -.CodeRay .color{color:#099} -.CodeRay .class-variable{color:#369} -.CodeRay .decorator{color:#b0b} -.CodeRay .definition{color:#099} -.CodeRay .delimiter{color:#000} -.CodeRay .doc{color:#970} -.CodeRay .doctype{color:#34b} -.CodeRay .doc-string{color:#d42} -.CodeRay .escape{color:#666} -.CodeRay .entity{color:#800} -.CodeRay .error{color:#808} -.CodeRay .exception{color:inherit} -.CodeRay .filename{color:#099} -.CodeRay .function{color:#900;font-weight:bold} -.CodeRay .global-variable{color:#008080} -.CodeRay .hex{color:#058} -.CodeRay .integer,.CodeRay .float{color:#099} -.CodeRay .include{color:#555} -.CodeRay .inline{color:#00} -.CodeRay .inline .inline{background:#ccc} -.CodeRay .inline .inline .inline{background:#bbb} -.CodeRay .inline .inline-delimiter{color:#d14} -.CodeRay .inline-delimiter{color:#d14} -.CodeRay .important{color:#555;font-weight:bold} -.CodeRay .interpreted{color:#b2b} -.CodeRay .instance-variable{color:#008080} -.CodeRay .label{color:#970} -.CodeRay .local-variable{color:#963} -.CodeRay .octal{color:#40e} -.CodeRay .predefined{color:#369} -.CodeRay .preprocessor{color:#579} -.CodeRay .pseudo-class{color:#555} -.CodeRay .directive{font-weight:bold} -.CodeRay .type{font-weight:bold} -.CodeRay .predefined-type{color:inherit} -.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold} -.CodeRay .key{color:#808} -.CodeRay .key .delimiter{color:#606} -.CodeRay .key .char{color:#80f} -.CodeRay .value{color:#088} -.CodeRay .regexp .delimiter{color:#808} -.CodeRay .regexp .content{color:#808} -.CodeRay .regexp .modifier{color:#808} -.CodeRay .regexp .char{color:#d14} -.CodeRay .regexp .function{color:#404;font-weight:bold} -.CodeRay .string{color:#d20} -.CodeRay .string .string .string{background:#ffd0d0} -.CodeRay .string .content{color:#d14} -.CodeRay .string .char{color:#d14} -.CodeRay .string .delimiter{color:#d14} -.CodeRay .shell{color:#d14} -.CodeRay .shell .delimiter{color:#d14} -.CodeRay .symbol{color:#990073} -.CodeRay .symbol .content{color:#a60} -.CodeRay .symbol .delimiter{color:#630} -.CodeRay .tag{color:#008080} -.CodeRay .tag-special{color:#d70} -.CodeRay .variable{color:#036} -.CodeRay .insert{background:#afa} -.CodeRay .delete{background:#faa} -.CodeRay .change{color:#aaf;background:#007} -.CodeRay .head{color:#f8f;background:#505} -.CodeRay .insert .insert{color:#080} -.CodeRay .delete .delete{color:#800} -.CodeRay .change .change{color:#66f} -.CodeRay .head .head{color:#f4f} - - body { - padding-top: 60px; - padding-bottom: 40px; - } - - .toc-like { - border-radius: 6px; - border: 1px solid #ccc; - } - - .toc-like li { - line-height: 30px; - text-indent: 10px; - } - - .toc-like li.custom-toc-header { - font-weight: bold; - background: #666; - color: white; - cursor: initial !important; - padding: 5px; - } - - .toc-like li.custom-toc-header a { - color: white; - font-style: normal; - text-shadow: none; - padding: 0; - } - - .toc-like li.custom-toc-header:hover a { - background: #666; - } - - .page-title { - text-align: left; - } - - #doc-content h2, - #doc-content h3, - #doc-content h4, - #doc-content h5, - #doc-content h6 { - padding-top: 0; - margin-top: 25px; - margin-bottom: 10px; - line-height: 1.4em; - } - - #doc-content h2 { - border-bottom: 1px solid lightgrey; - } - - - </style> - - <script type="text/javascript"> - - var _gaq = _gaq || []; - _gaq.push(['_setAccount', 'UA-36103647-1']); - _gaq.push(['_trackPageview']); - - (function () { - var ga = document.createElement('script'); - ga.type = 'text/javascript'; - ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; - s.parentNode.insertBefore(ga, s); - })(); - - </script> -</head> - -<body> - -<div class="navbar navbar-fixed-top"> - <div class="navbar-inner"> - <div class="container"> - <a class="btn btn-navbar" data-toggle="collapse" - data-target=".nav-collapse"> <span class="icon-bar"></span> <span - class="icon-bar"></span> <span class="icon-bar"></span> - </a> - <a class="brand logocolor" href="../index.html">Apache DeltaSpike</a> - - <div class="nav-collapse"> - - - <ul class="nav"> - <li><a href="../index.html">Home</a></li> - <li class="active"><a href="../documentation">Documentation</a></li> - <li ><a href="../javadoc.html">Javadoc</a></li> - <li ><a href="../source.html">Source</a></li> - <li ><a href="../download.html">Download</a></li> - <li ><a href="../community.html">Community</a></li> - <!-- <li><a href="./support.html">Support</a></li> --> - <li ><a href="../news.html">News</a></li> - </ul> - </div> - <!--/.nav-collapse --> - <form id="search-form" action="https://www.google.com/search" - method="get" class="navbar-search pull-right"> - <input value="deltaspike.apache.org" name="sitesearch" - type="hidden"> <input class="search-query" name="q" - id="query" type="text"> - </form> - </div> - </div> -</div> - -<div class="container"> - <div class="row-fluid"> - - - - <div class="span8"> - <div class="page-title"> - <h1>Security Module</h1> - </div> - - <div id="doc-content"> - <div class="sect1"> -<h2 id="_overview">Overview</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>The Security module provides APIs for authorization of method invocations.</p> -</div> -<div class="paragraph"> -<p>There are two different APIs provided for two different approaches — one simple interceptor-style API and another for more complex scenarios.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><strong><a href="#_simple_interceptor_style_authorization">Simple interceptor-style API</a>:</strong> the method that is to be secured is loosely coupled to a predicate method -(called <em>authorizer</em> method) which decides whether the secured method invocation should proceed. Similarly to CDI -interceptors, the secured method and the authorizer are tied together using a binding annotation — <code>@SecurityBindingType</code> in this case.</p> -</li> -<li> -<p><strong><a href="#_advanced_authorization">Advanced API</a>:</strong> this API offers fine-grained control over the authorization process. Multiple independent <em>voters</em> can participate in making the authorization decision and possibly return <em>security violations</em> and thus prevent the method invocation. The voters share a common context. This API is suitable for integration with third-party security frameworks. Also, this API can be used to <a href="jsf.html#_security_integration_via_secured">secure JSF view access</a> when using the DeltaSpike JSF module.</p> -</li> -</ul> -</div> -</div> -</div> -<div class="sect1"> -<h2 id="_project_setup">Project Setup</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>The configuration information provided here is for Maven-based projects and it assumes that you have already declared the DeltaSpike version and DeltaSpike Core module for your projects, as detailed in <a href="configure.html">Configure DeltaSpike in Your Projects</a>. For Maven-independent projects, see <a href="configure.html#config-maven-indep">Configure DeltaSpike in Maven-independent Projects</a>.</p> -</div> -<div class="sect2"> -<h3 id="_1_declare_security_module_dependencies">1. Declare Security Module Dependencies</h3> -<div class="paragraph"> -<p>Add the Security module to the list of dependencies in the project <code>pom.xml</code> file using this code snippet:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><dependency></span> - <span class="tag"><groupId></span>org.apache.deltaspike.modules<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>deltaspike-security-module-api<span class="tag"></artifactId></span> - <span class="tag"><version></span>${deltaspike.version}<span class="tag"></version></span> - <span class="tag"><scope></span>compile<span class="tag"></scope></span> -<span class="tag"></dependency></span> - -<span class="tag"><dependency></span> - <span class="tag"><groupId></span>org.apache.deltaspike.modules<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>deltaspike-security-module-impl<span class="tag"></artifactId></span> - <span class="tag"><version></span>${deltaspike.version}<span class="tag"></version></span> - <span class="tag"><scope></span>runtime<span class="tag"></scope></span> -<span class="tag"></dependency></span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>Or if you’re using Gradle, add these dependencies to your <code>build.gradle</code>:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code> runtime 'org.apache.deltaspike.modules:deltaspike-security-module-impl' - compile 'org.apache.deltaspike.modules:deltaspike-security-module-api'</code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="_2_enable_the_securityinterceptor">2. Enable the SecurityInterceptor</h3> -<div class="paragraph"> -<p>For CDI 1.0 (or DeltaSpike v1.1.0 and earlier together with CDI 1.1+), you must enable the security interceptor in the project <code>beans.xml</code> file:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><beans></span> - <span class="comment"><!-- Not needed with CDI 1.1+ and DeltaSpike v1.1.1+ --></span> - <span class="tag"><interceptors></span> - <span class="tag"><class></span>org.apache.deltaspike.security.impl.extension.SecurityInterceptor<span class="tag"></class></span> - <span class="tag"></interceptors></span> -<span class="tag"></beans></span></code></pre> -</div> -</div> -</div> -</div> -</div> -<div class="sect1"> -<h2 id="_simple_interceptor_style_authorization">Simple interceptor-style authorization</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>This feature of the Security module intercepts method calls and performs a security check before invocation is allowed to proceed.</p> -</div> -<div class="paragraph"> -<p>The first piece of code required to use this API is a <em>security binding</em> annotation. This is what we will use to add security behavior to our business classes and methods.</p> -</div> -<div class="listingblock"> -<div class="title">Create the security binding annotation</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Retention</span>(value = RUNTIME) -<span class="annotation">@Target</span>({TYPE, METHOD}) -<span class="annotation">@Documented</span> -<span class="annotation">@SecurityBindingType</span> -<span class="directive">public</span> <span class="annotation">@interface</span> UserLoggedIn {}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Next, we must define an <em>authorizer</em> class to implement behavior for our -custom security binding type. This class is simply a CDI bean which -declares a method annotated <code>@Secures</code>, qualified with the security binding -annotation we created in the first step.</p> -</div> -<div class="paragraph"> -<p>This method has access to the <code>InvocationContext</code> of the method call, so -if we need to access parameter arguments, we can do so using the given -context. Note that we may also inject other beans into the parameter -list of our authorizer method.</p> -</div> -<div class="listingblock"> -<div class="title">Create the authorizer</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> -<span class="directive">public</span> <span class="type">class</span> <span class="class">LoggedInAuthorizer</span> -{ - <span class="annotation">@Secures</span> - <span class="annotation">@UserLoggedIn</span> - <span class="directive">public</span> <span class="type">boolean</span> doSecuredCheck(InvocationContext invocationContext, BeanManager manager, <span class="predefined-type">Identity</span> identity) <span class="directive">throws</span> <span class="exception">Exception</span> - { - <span class="keyword">return</span> identity.isLoggedIn(); <span class="comment">// perform security check</span> - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>We can then use our new annotation to secure business or bean methods. -This binding annotation may be placed on the entire class (securing all -methods) or on individual methods that you wish to secure.</p> -</div> -<div class="listingblock"> -<div class="title">Secure a bean method</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> -<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean1</span> -{ - <span class="annotation">@UserLoggedIn</span> - <span class="directive">public</span> <span class="type">void</span> doSomething(Thing thing) - { - thing.doSomething(); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Next, we may access parameter values from the method invocation directly -in our authorizer bean by creating custom <code>@SecurityParameterBinding</code> -types; this is a simple step once we have completed the work above:</p> -</div> -<div class="listingblock"> -<div class="title">Create a parameter binding annotation</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Retention</span>(value = RUNTIME) -<span class="annotation">@Target</span>({PARAMETER}) -<span class="annotation">@Documented</span> -<span class="annotation">@SecurityParameterBinding</span> -<span class="directive">public</span> <span class="annotation">@interface</span> CurrentThing { -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Now, when a secured method is invoked, we can inject actual parameter -values as arguments into our authorizer method, providing domain-level -security in our applications:</p> -</div> -<div class="listingblock"> -<div class="title">Update the authorizer to use parameter binding</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> -<span class="directive">public</span> <span class="type">class</span> <span class="class">CustomAuthorizer</span> -{ - <span class="annotation">@Secures</span> - <span class="annotation">@UserLoggedIn</span> - <span class="directive">public</span> <span class="type">boolean</span> doSecuredCheck(InvocationContext invocationContext, BeanManager manager, <span class="predefined-type">Identity</span> identity, <span class="annotation">@CurrentThing</span> Thing thing) <span class="directive">throws</span> <span class="exception">Exception</span> - { - <span class="keyword">return</span> thing.hasMember(identity); <span class="comment">// perform security check against our method parameter</span> - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Note that our business method must also be annotated.</p> -</div> -<div class="listingblock"> -<div class="title">Complete the Parameter Binding</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> -<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean1</span> -{ - <span class="annotation">@UserLoggedIn</span> - <span class="directive">public</span> <span class="type">void</span> doSomething(<span class="annotation">@CurrentThing</span> Thing thing) - { - thing.doSomething(); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Our method is now secured, and we are able to use given parameter values -as part of our security authorizer!</p> -</div> -<div class="paragraph"> -<p>There may be cases where you may want to base your authorization logic -on the result of the secured method and do the security check after the -method invocation. Just use the same security binding type for that -case:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> -<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean1</span> -{ - <span class="annotation">@UserLoggedIn</span> - <span class="directive">public</span> Thing loadSomething() - { - <span class="keyword">return</span> thingLoader.load(); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Now you need to access the return value in the authorizer method. You -can inject it using the <code>@SecuredReturn</code> annotation. Update the authorizer -to use a secured return value:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> -<span class="directive">public</span> <span class="type">class</span> <span class="class">CustomAuthorizer</span> -{ - <span class="annotation">@Secures</span> - <span class="annotation">@UserLoggedIn</span> - <span class="directive">public</span> <span class="type">boolean</span> doSecuredCheck(<span class="annotation">@SecuredReturn</span> Thing thing, <span class="predefined-type">Identity</span> identity) <span class="directive">throws</span> <span class="exception">Exception</span> - { - <span class="keyword">return</span> thing.hasMember(identity); <span class="comment">// perform security check against the return value</span> -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Now the authorization will take place after the method invocation using -the return value of the business method.</p> -</div> -</div> -</div> -<div class="sect1"> -<h2 id="_advanced_authorization">Advanced authorization</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>This is an alternative to the simple annotation-based interceptor-style API. This API uses the annotation <code>@Secured</code> and is mainly a hook for integration of custom security concepts and third-party frameworks. The DeltaSpike Security module is <em>not</em> a full application security solution, but some of the other DeltaSpike modules are security-enabled and use this API (e.g. correct behaviour within custom scope implementations,…​). Internally, this <code>@Secured</code> API uses the <code>@Secures</code>/<code>@SecurityBindingType</code> API.</p> -</div> -<div class="paragraph"> -<p>(In MyFaces CODI it was originally a CDI interceptor. This part changed -a bit, because between the interceptor and <code>@Secured</code> is the -<code>@SecurityBindingType</code> concept which triggers <code>@Secured</code> as on possible -approach. Therefore the basic behaviour remains the same and you can -think about it like an interceptor.)</p> -</div> -<div class="paragraph"> -<p>The entry point to this API is the <code>@Secured</code> annotation placed either on the whole class — enabling security for all methods — or on individual methods. The only other prerequisite is at least one <code>AccessDecisionVoter</code> implementation, explained in the next section.</p> -</div> -<div class="listingblock"> -<div class="title">Securing All Intercepted Methods of a CDI Bean</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="comment">//...</span> -<span class="annotation">@Secured</span>(CustomAccessDecisionVoter.class) -<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean</span> -{ - <span class="comment">//...</span> -}</code></pre> -</div> -</div> -<div class="listingblock"> -<div class="title">Securing Specific Methods</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="comment">//...</span> -<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean</span> -{ - <span class="annotation">@Secured</span>(CustomAccessDecisionVoter.class) - <span class="directive">public</span> <span class="predefined-type">String</span> getResult() - { - <span class="comment">//...</span> - } -}</code></pre> -</div> -</div> -<div class="sect2"> -<h3 id="_accessdecisionvoter">AccessDecisionVoter</h3> -<div class="paragraph"> -<p>This interface is (besides the <code>@Secured</code> annotation) the most important -part of the concept. Both artifact types are also the only required -parts:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">CustomAccessDecisionVoter</span> <span class="directive">implements</span> AccessDecisionVoter -{ - <span class="annotation">@Override</span> - <span class="directive">public</span> <span class="predefined-type">Set</span><SecurityViolation> checkPermission(AccessDecisionVoterContext accessDecisionVoterContext) - { - <span class="predefined-type">Method</span> method = accessDecisionVoterContext.<InvocationContext>getSource().getMethod(); - - <span class="comment">//...</span> - } -}</code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="_securityviolation">SecurityViolation</h3> -<div class="paragraph"> -<p>In case of a detected violation a <code>SecurityViolation</code> has to be added to -the result returned by the <code>AccessDecisionVoter</code>.</p> -</div> -</div> -<div class="sect2"> -<h3 id="_abstractaccessdecisionvoter">AbstractAccessDecisionVoter</h3> -<div class="paragraph"> -<p>You can also implement the abstract class <code>AbstractAccessDecisionVoter</code>. -This is a convenience class which allows an easier usage:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">CustomAccessDecisionVoter</span> <span class="directive">extends</span> AbstractAccessDecisionVoter -{ - - <span class="annotation">@Override</span> - <span class="directive">protected</span> <span class="type">void</span> checkPermission(AccessDecisionVoterContext accessDecisionVoterContext, - <span class="predefined-type">Set</span><SecurityViolation> violations) - { - <span class="comment">// check for violations</span> - violations.add(newSecurityViolation(<span class="string"><span class="delimiter">"</span><span class="content">access not allowed due to ...</span><span class="delimiter">"</span></span>)); - } -}</code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="__secured_and_stereotypes_with_custom_metadata">@Secured and stereotypes with custom metadata</h3> -<div class="paragraph"> -<p>If there are multiple <code>AccessDecisionVoter</code> and maybe in different -constellations, it is easier to provide an expressive CDI stereotypes for -it. Later on that also allows to change the behaviour in a central -place.</p> -</div> -<div class="listingblock"> -<div class="title">Stereotype Support of @Secured</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Named</span> -<span class="annotation">@Admin</span> -<span class="directive">public</span> <span class="type">class</span> <span class="class">MyBean</span> <span class="directive">implements</span> <span class="predefined-type">Serializable</span> -{ - <span class="comment">//...</span> -} - -<span class="comment">//...</span> -<span class="annotation">@Stereotype</span> -<span class="annotation">@Secured</span>(RoleAccessDecisionVoter.class) -<span class="directive">public</span> <span class="annotation">@interface</span> Admin -{ -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Furthermore, it is possible to provide custom metadata easily.</p> -</div> -<div class="listingblock"> -<div class="title">Stereotype of @Secured with custom metadata</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Named</span> -<span class="annotation">@Admin</span>(securityLevel=<span class="integer">3</span>) -<span class="directive">public</span> <span class="type">class</span> <span class="class">MyBean</span> <span class="directive">implements</span> <span class="predefined-type">Serializable</span> -{ - <span class="comment">//...</span> -} - -<span class="comment">//...</span> -<span class="annotation">@Stereotype</span> -<span class="annotation">@Secured</span>(RoleAccessDecisionVoter.class) -<span class="directive">public</span> <span class="annotation">@interface</span> Admin -{ - <span class="type">int</span> securityLevel(); -} - -<span class="annotation">@ApplicationScoped</span> -<span class="directive">public</span> <span class="type">class</span> <span class="class">RoleAccessDecisionVoter</span> <span class="directive">implements</span> AccessDecisionVoter -{ - <span class="directive">private</span> <span class="directive">static</span> <span class="directive">final</span> <span class="type">long</span> serialVersionUID = -<span class="integer">8007511215776345835L</span>; - - <span class="directive">public</span> <span class="predefined-type">Set</span><SecurityViolation> checkPermission(AccessDecisionVoterContext voterContext) - { - Admin admin = voterContext.getMetaDataFor(Admin.class.getName(), Admin.class); - <span class="type">int</span> level = admin.securityLevel(); - <span class="comment">//...</span> - } -}</code></pre> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="_accessdecisionvotercontext">AccessDecisionVoterContext</h3> -<div class="paragraph"> -<p>Because the <code>AccessDecisionVoter</code> can be chained, -<code>AccessDecisionVoterContext</code> allows to get the current state as well as -the results of the security check.</p> -</div> -<div class="paragraph"> -<p>There are several methods that can be useful</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>getState()</code> - Exposes the current state : INITIAL, VOTE_IN_PROGRESS, VIOLATION_FOUND, NO_VIOLATION_FOUND</p> -</li> -<li> -<p><code>getViolations()</code> - Exposes the found violations</p> -</li> -<li> -<p><code>getSource()</code> - Exposes, for example, the current instance of <code>javax.interceptor.InvocationContext</code> in combination with <code>@Secured</code> used as interceptor.</p> -</li> -<li> -<p><code>getMetaData()</code> - Exposes the found meta-data, for example the view-config-class if <code>@Secured</code> is used in combination with type-safe view-configs</p> -</li> -<li> -<p><code>getMetaDataFor(String, Class<T>)</code> - Exposes meta-data for the given key</p> -</li> -</ul> -</div> -</div> -<div class="sect2"> -<h3 id="_securitystrategy_spi">SecurityStrategy SPI</h3> -<div class="paragraph"> -<p>The <code>SecurityStrategy</code> interface allows to provide a custom -implementation which should be used for <code>@Secured</code>. Provide a custom -implementation as bean-class in combination with <code>@Alternative</code> or -<code>@Specializes</code> (or as global-alternative).</p> -</div> -<div class="paragraph"> -<p>In case of global-alternatives an additional configuration needs to be added to -<code>/META-INF/apache-deltaspike.properties</code>.</p> -</div> -<div class="listingblock"> -<div class="title">Example</div> -<div class="content"> -<pre>globalAlternatives.org.apache.deltaspike.security.spi.authorization.SecurityStrategy=mypackage.CustomSecurityStrategy</pre> -</div> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -The configuration for global alternatives is following the pattern: -<code>globalAlternatives.<em><interface-name></em>=<em><implementation-class-name></em></code> -</td> -</tr> -</table> -</div> -</div> -<div class="sect2"> -<h3 id="_examples">Examples</h3> -<div class="sect3"> -<h4 id="_redirect_to_requested_page_after_login">Redirect to requested page after login</h4> -<div class="paragraph"> -<p>DeltaSpike can be combined with pure CDI or with any other security -frameworks (like PicketLink) to track the denied page and make it -available after user logs in.</p> -</div> -<div class="paragraph"> -<p>An example of this use case is available in the examples module in the DeltaSpike repository:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><a href="https://github.com/apache/deltaspike/tree/master/deltaspike/examples/security-requested-page-after-login-cdi">Making initially requested secured page available for redirect after login with CDI</a></p> -</li> -<li> -<p><a href="https://github.com/apache/deltaspike/tree/master/deltaspike/examples/security-requested-page-after-login-picketlink">Making initially requested secured page available for redirect after login with PicketLink</a></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>The relevant classes are <code>AuthenticationListener</code> and <code>LoggedInAccessDecisionVoter</code>.</p> -</div> -</div> -</div> -</div> -</div> - </div> - </div> - - - <div class="span4"> - <div id="toc"> - <div class="moduledeps"> - <ul class="toc-like nav nav-list"> - - <li class="custom-toc-header">Depends on</li> - - <li><a href="core.html">Core</a></li> - - - - - <li class="custom-toc-header">Table of Contents</li> - - </ul> - </div> - </div> - - <div class="fallback-toc"> - <ul class="sectlevel1"> -<li><a href="#_overview">Overview</a></li> -<li><a href="#_project_setup">Project Setup</a> -<ul class="sectlevel2"> -<li><a href="#_1_declare_security_module_dependencies">1. Declare Security Module Dependencies</a></li> -<li><a href="#_2_enable_the_securityinterceptor">2. Enable the SecurityInterceptor</a></li> -</ul> -</li> -<li><a href="#_simple_interceptor_style_authorization">Simple interceptor-style authorization</a></li> -<li><a href="#_advanced_authorization">Advanced authorization</a> -<ul class="sectlevel2"> -<li><a href="#_accessdecisionvoter">AccessDecisionVoter</a></li> -<li><a href="#_securityviolation">SecurityViolation</a></li> -<li><a href="#_abstractaccessdecisionvoter">AbstractAccessDecisionVoter</a></li> -<li><a href="#__secured_and_stereotypes_with_custom_metadata">@Secured and stereotypes with custom metadata</a></li> -<li><a href="#_accessdecisionvotercontext">AccessDecisionVoterContext</a></li> -<li><a href="#_securitystrategy_spi">SecurityStrategy SPI</a></li> -<li><a href="#_examples">Examples</a> -<ul class="sectlevel3"> -<li><a href="#_redirect_to_requested_page_after_login">Redirect to requested page after login</a></li> -</ul> -</li> -</ul> -</li> -</ul> - </div> - - </div> - - - </div> - <div class="row"> - <hr> - <footer> - <p>Copyright © 2011-2016 The Apache Software Foundation, - Licensed under the Apache License, Version 2.0.</p> - - <p>Apache and the Apache feather logo are trademarks of The Apache Software Foundation.</p> - </footer> - </div> -</div> - -</body> +<!DOCTYPE html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="description" content="deltaspike-generate-pages"> + <meta name="author" content="chm"> + <!-- No caching headers --> + <meta http-equiv="cache-control" content="no-cache"/> + <meta http-equiv="pragma" content="no-cache"/> + <meta http-equiv="expires" content="-1"/> + + <title>Security Module</title> + + <!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + --> + + <!-- Styles --> + <link href="https://deltaspike.apache.org/resources/css/bootstrap.css" rel="stylesheet"> + <link href="https://deltaspike.apache.org/resources/css/bootstrap-responsive.css" rel="stylesheet"> + <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/3.1.0/css/font-awesome.min.css" rel="stylesheet"> + + + + + <!-- Tocify - nice dynamic autoscrolling TOC --> + <link href="https://cdnjs.cloudflare.com/ajax/libs/jquery.tocify/1.9.0/stylesheets/jquery.tocify.min.css" rel="stylesheet"> + <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.tocify/1.9.0/javascripts/jquery.tocify.min.js"></script> + + + <script type="text/javascript"> + $(function () { + $("#toc").tocify({ + scrollTo: 50, + extendPage: true, + context: "#doc-content", + selectors: "h2,h3,h4,h5" + }); + $(".fallback-toc").hide(); + }); + </script> + + + <style type="text/css"> + /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */ +/*pre.CodeRay {background-color:#f7f7f8;}*/ +.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em} +.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)} +.CodeRay .line-numbers strong{font-weight: normal} +table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none} +table.CodeRay td{vertical-align: top} +table.CodeRay td.line-numbers{text-align:right} +table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)} +table.CodeRay td.code{padding:0 0 0 .5em} +table.CodeRay td.code>pre{padding:0} +.CodeRay .debug{color:#fff !important;background:#000080 !important} +.CodeRay .annotation{color:#007} +.CodeRay .attribute-name{color:#000080} +.CodeRay .attribute-value{color:#700} +.CodeRay .binary{color:#509} +.CodeRay .comment{color:#998;font-style:italic} +.CodeRay .char{color:#04d} +.CodeRay .char .content{color:#04d} +.CodeRay .char .delimiter{color:#039} +.CodeRay .class{color:#458;font-weight:bold} +.CodeRay .complex{color:#a08} +.CodeRay .constant,.CodeRay .predefined-constant{color:#008080} +.CodeRay .color{color:#099} +.CodeRay .class-variable{color:#369} +.CodeRay .decorator{color:#b0b} +.CodeRay .definition{color:#099} +.CodeRay .delimiter{color:#000} +.CodeRay .doc{color:#970} +.CodeRay .doctype{color:#34b} +.CodeRay .doc-string{color:#d42} +.CodeRay .escape{color:#666} +.CodeRay .entity{color:#800} +.CodeRay .error{color:#808} +.CodeRay .exception{color:inherit} +.CodeRay .filename{color:#099} +.CodeRay .function{color:#900;font-weight:bold} +.CodeRay .global-variable{color:#008080} +.CodeRay .hex{color:#058} +.CodeRay .integer,.CodeRay .float{color:#099} +.CodeRay .include{color:#555} +.CodeRay .inline{color:#00} +.CodeRay .inline .inline{background:#ccc} +.CodeRay .inline .inline .inline{background:#bbb} +.CodeRay .inline .inline-delimiter{color:#d14} +.CodeRay .inline-delimiter{color:#d14} +.CodeRay .important{color:#555;font-weight:bold} +.CodeRay .interpreted{color:#b2b} +.CodeRay .instance-variable{color:#008080} +.CodeRay .label{color:#970} +.CodeRay .local-variable{color:#963} +.CodeRay .octal{color:#40e} +.CodeRay .predefined{color:#369} +.CodeRay .preprocessor{color:#579} +.CodeRay .pseudo-class{color:#555} +.CodeRay .directive{font-weight:bold} +.CodeRay .type{font-weight:bold} +.CodeRay .predefined-type{color:inherit} +.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold} +.CodeRay .key{color:#808} +.CodeRay .key .delimiter{color:#606} +.CodeRay .key .char{color:#80f} +.CodeRay .value{color:#088} +.CodeRay .regexp .delimiter{color:#808} +.CodeRay .regexp .content{color:#808} +.CodeRay .regexp .modifier{color:#808} +.CodeRay .regexp .char{color:#d14} +.CodeRay .regexp .function{color:#404;font-weight:bold} +.CodeRay .string{color:#d20} +.CodeRay .string .string .string{background:#ffd0d0} +.CodeRay .string .content{color:#d14} +.CodeRay .string .char{color:#d14} +.CodeRay .string .delimiter{color:#d14} +.CodeRay .shell{color:#d14} +.CodeRay .shell .delimiter{color:#d14} +.CodeRay .symbol{color:#990073} +.CodeRay .symbol .content{color:#a60} +.CodeRay .symbol .delimiter{color:#630} +.CodeRay .tag{color:#008080} +.CodeRay .tag-special{color:#d70} +.CodeRay .variable{color:#036} +.CodeRay .insert{background:#afa} +.CodeRay .delete{background:#faa} +.CodeRay .change{color:#aaf;background:#007} +.CodeRay .head{color:#f8f;background:#505} +.CodeRay .insert .insert{color:#080} +.CodeRay .delete .delete{color:#800} +.CodeRay .change .change{color:#66f} +.CodeRay .head .head{color:#f4f} + + body { + padding-top: 60px; + padding-bottom: 40px; + } + + .toc-like { + border-radius: 6px; + border: 1px solid #ccc; + } + + .toc-like li { + line-height: 30px; + text-indent: 10px; + } + + .toc-like li.custom-toc-header { + font-weight: bold; + background: #666; + color: white; + cursor: initial !important; + padding: 5px; + } + + .toc-like li.custom-toc-header a { + color: white; + font-style: normal; + text-shadow: none; + padding: 0; + } + + .toc-like li.custom-toc-header:hover a { + background: #666; + } + + .page-title { + text-align: left; + } + + #doc-content h2, + #doc-content h3, + #doc-content h4, + #doc-content h5, + #doc-content h6 { + padding-top: 0; + margin-top: 25px; + margin-bottom: 10px; + line-height: 1.4em; + } + + #doc-content h2 { + border-bottom: 1px solid lightgrey; + } + + + </style> + + <script type="text/javascript"> + + var _gaq = _gaq || []; + _gaq.push(['_setAccount', 'UA-36103647-1']); + _gaq.push(['_trackPageview']); + + (function () { + var ga = document.createElement('script'); + ga.type = 'text/javascript'; + ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(ga, s); + })(); + + </script> +</head> + +<body> + +<div class="navbar navbar-fixed-top"> + <div class="navbar-inner"> + <div class="container"> + <a class="btn btn-navbar" data-toggle="collapse" + data-target=".nav-collapse"> <span class="icon-bar"></span> <span + class="icon-bar"></span> <span class="icon-bar"></span> + </a> + <a class="brand logocolor" href="../index.html">Apache DeltaSpike</a> + + <div class="nav-collapse"> + + + <ul class="nav"> + <li><a href="../index.html">Home</a></li> + <li class="active"><a href="../documentation">Documentation</a></li> + <li ><a href="../javadoc.html">Javadoc</a></li> + <li ><a href="../source.html">Source</a></li> + <li ><a href="../download.html">Download</a></li> + <li ><a href="../community.html">Community</a></li> + <!-- <li><a href="./support.html">Support</a></li> --> + <li ><a href="../news.html">News</a></li> + </ul> + </div> + <!--/.nav-collapse --> + <form id="search-form" action="https://www.google.com/search" + method="get" class="navbar-search pull-right"> + <input value="deltaspike.apache.org" name="sitesearch" + type="hidden"> <input class="search-query" name="q" + id="query" type="text"> + </form> + </div> + </div> +</div> + +<div class="container"> + <div class="row-fluid"> + + + + <div class="span8"> + <div class="page-title"> + <h1>Security Module</h1> + </div> + + <div id="doc-content"> + <div class="sect1"> +<h2 id="_overview">Overview</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>The Security module provides APIs for authorization of method invocations.</p> +</div> +<div class="paragraph"> +<p>There are two different APIs provided for two different approaches — one simple interceptor-style API and another for more complex scenarios.</p> +</div> +<div class="ulist"> +<ul> +<li> +<p><strong><a href="#_simple_interceptor_style_authorization">Simple interceptor-style API</a>:</strong> the method that is to be secured is loosely coupled to a predicate method +(called <em>authorizer</em> method) which decides whether the secured method invocation should proceed. Similarly to CDI +interceptors, the secured method and the authorizer are tied together using a binding annotation — <code>@SecurityBindingType</code> in this case.</p> +</li> +<li> +<p><strong><a href="#_advanced_authorization">Advanced API</a>:</strong> this API offers fine-grained control over the authorization process. Multiple independent <em>voters</em> can participate in making the authorization decision and possibly return <em>security violations</em> and thus prevent the method invocation. The voters share a common context. This API is suitable for integration with third-party security frameworks. Also, this API can be used to <a href="jsf.html#_security_integration_via_secured">secure JSF view access</a> when using the DeltaSpike JSF module.</p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_project_setup">Project Setup</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>The configuration information provided here is for Maven-based projects and it assumes that you have already declared the DeltaSpike version and DeltaSpike Core module for your projects, as detailed in <a href="configure.html">Configure DeltaSpike in Your Projects</a>. For Maven-independent projects, see <a href="configure.html#config-maven-indep">Configure DeltaSpike in Maven-independent Projects</a>.</p> +</div> +<div class="sect2"> +<h3 id="_1_declare_security_module_dependencies">1. Declare Security Module Dependencies</h3> +<div class="paragraph"> +<p>Add the Security module to the list of dependencies in the project <code>pom.xml</code> file using this code snippet:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><dependency></span> + <span class="tag"><groupId></span>org.apache.deltaspike.modules<span class="tag"></groupId></span> + <span class="tag"><artifactId></span>deltaspike-security-module-api<span class="tag"></artifactId></span> + <span class="tag"><version></span>${deltaspike.version}<span class="tag"></version></span> + <span class="tag"><scope></span>compile<span class="tag"></scope></span> +<span class="tag"></dependency></span> + +<span class="tag"><dependency></span> + <span class="tag"><groupId></span>org.apache.deltaspike.modules<span class="tag"></groupId></span> + <span class="tag"><artifactId></span>deltaspike-security-module-impl<span class="tag"></artifactId></span> + <span class="tag"><version></span>${deltaspike.version}<span class="tag"></version></span> + <span class="tag"><scope></span>runtime<span class="tag"></scope></span> +<span class="tag"></dependency></span></code></pre> +</div> +</div> +<div class="paragraph"> +<p>Or if you’re using Gradle, add these dependencies to your <code>build.gradle</code>:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="CodeRay highlight"><code> runtime 'org.apache.deltaspike.modules:deltaspike-security-module-impl' + compile 'org.apache.deltaspike.modules:deltaspike-security-module-api'</code></pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_2_enable_the_securityinterceptor">2. Enable the SecurityInterceptor</h3> +<div class="paragraph"> +<p>For CDI 1.0 (or DeltaSpike v1.1.0 and earlier together with CDI 1.1+), you must enable the security interceptor in the project <code>beans.xml</code> file:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><beans></span> + <span class="comment"><!-- Not needed with CDI 1.1+ and DeltaSpike v1.1.1+ --></span> + <span class="tag"><interceptors></span> + <span class="tag"><class></span>org.apache.deltaspike.security.impl.extension.SecurityInterceptor<span class="tag"></class></span> + <span class="tag"></interceptors></span> +<span class="tag"></beans></span></code></pre> +</div> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_simple_interceptor_style_authorization">Simple interceptor-style authorization</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>This feature of the Security module intercepts method calls and performs a security check before invocation is allowed to proceed.</p> +</div> +<div class="paragraph"> +<p>The first piece of code required to use this API is a <em>security binding</em> annotation. This is what we will use to add security behavior to our business classes and methods.</p> +</div> +<div class="listingblock"> +<div class="title">Create the security binding annotation</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Retention</span>(value = RUNTIME) +<span class="annotation">@Target</span>({TYPE, METHOD}) +<span class="annotation">@Documented</span> +<span class="annotation">@SecurityBindingType</span> +<span class="directive">public</span> <span class="annotation">@interface</span> UserLoggedIn {}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>Next, we must define an <em>authorizer</em> class to implement behavior for our +custom security binding type. This class is simply a CDI bean which +declares a method annotated <code>@Secures</code>, qualified with the security binding +annotation we created in the first step.</p> +</div> +<div class="paragraph"> +<p>This method has access to the <code>InvocationContext</code> of the method call, so +if we need to access parameter arguments, we can do so using the given +context. Note that we may also inject other beans into the parameter +list of our authorizer method.</p> +</div> +<div class="listingblock"> +<div class="title">Create the authorizer</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> +<span class="directive">public</span> <span class="type">class</span> <span class="class">LoggedInAuthorizer</span> +{ + <span class="annotation">@Secures</span> + <span class="annotation">@UserLoggedIn</span> + <span class="directive">public</span> <span class="type">boolean</span> doSecuredCheck(InvocationContext invocationContext, BeanManager manager, <span class="predefined-type">Identity</span> identity) <span class="directive">throws</span> <span class="exception">Exception</span> + { + <span class="keyword">return</span> identity.isLoggedIn(); <span class="comment">// perform security check</span> + } +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>We can then use our new annotation to secure business or bean methods. +This binding annotation may be placed on the entire class (securing all +methods) or on individual methods that you wish to secure.</p> +</div> +<div class="listingblock"> +<div class="title">Secure a bean method</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> +<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean1</span> +{ + <span class="annotation">@UserLoggedIn</span> + <span class="directive">public</span> <span class="type">void</span> doSomething(Thing thing) + { + thing.doSomething(); + } +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>Next, we may access parameter values from the method invocation directly +in our authorizer bean by creating custom <code>@SecurityParameterBinding</code> +types; this is a simple step once we have completed the work above:</p> +</div> +<div class="listingblock"> +<div class="title">Create a parameter binding annotation</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Retention</span>(value = RUNTIME) +<span class="annotation">@Target</span>({PARAMETER}) +<span class="annotation">@Documented</span> +<span class="annotation">@SecurityParameterBinding</span> +<span class="directive">public</span> <span class="annotation">@interface</span> CurrentThing { +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>Now, when a secured method is invoked, we can inject actual parameter +values as arguments into our authorizer method, providing domain-level +security in our applications:</p> +</div> +<div class="listingblock"> +<div class="title">Update the authorizer to use parameter binding</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> +<span class="directive">public</span> <span class="type">class</span> <span class="class">CustomAuthorizer</span> +{ + <span class="annotation">@Secures</span> + <span class="annotation">@UserLoggedIn</span> + <span class="directive">public</span> <span class="type">boolean</span> doSecuredCheck(InvocationContext invocationContext, BeanManager manager, <span class="predefined-type">Identity</span> identity, <span class="annotation">@CurrentThing</span> Thing thing) <span class="directive">throws</span> <span class="exception">Exception</span> + { + <span class="keyword">return</span> thing.hasMember(identity); <span class="comment">// perform security check against our method parameter</span> + } +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>Note that our business method must also be annotated.</p> +</div> +<div class="listingblock"> +<div class="title">Complete the Parameter Binding</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> +<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean1</span> +{ + <span class="annotation">@UserLoggedIn</span> + <span class="directive">public</span> <span class="type">void</span> doSomething(<span class="annotation">@CurrentThing</span> Thing thing) + { + thing.doSomething(); + } +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>Our method is now secured, and we are able to use given parameter values +as part of our security authorizer!</p> +</div> +<div class="paragraph"> +<p>There may be cases where you may want to base your authorization logic +on the result of the secured method and do the security check after the +method invocation. Just use the same security binding type for that +case:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> +<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean1</span> +{ + <span class="annotation">@UserLoggedIn</span> + <span class="directive">public</span> Thing loadSomething() + { + <span class="keyword">return</span> thingLoader.load(); + } +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>Now you need to access the return value in the authorizer method. You +can inject it using the <code>@SecuredReturn</code> annotation. Update the authorizer +to use a secured return value:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span> +<span class="directive">public</span> <span class="type">class</span> <span class="class">CustomAuthorizer</span> +{ + <span class="annotation">@Secures</span> + <span class="annotation">@UserLoggedIn</span> + <span class="directive">public</span> <span class="type">boolean</span> doSecuredCheck(<span class="annotation">@SecuredReturn</span> Thing thing, <span class="predefined-type">Identity</span> identity) <span class="directive">throws</span> <span class="exception">Exception</span> + { + <span class="keyword">return</span> thing.hasMember(identity); <span class="comment">// perform security check against the return value</span> +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>Now the authorization will take place after the method invocation using +the return value of the business method.</p> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_advanced_authorization">Advanced authorization</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>This is an alternative to the simple annotation-based interceptor-style API. This API uses the annotation <code>@Secured</code> and is mainly a hook for integration of custom security concepts and third-party frameworks. The DeltaSpike Security module is <em>not</em> a full application security solution, but some of the other DeltaSpike modules are security-enabled and use this API (e.g. correct behaviour within custom scope implementations,…​). Internally, this <code>@Secured</code> API uses the <code>@Secures</code>/<code>@SecurityBindingType</code> API.</p> +</div> +<div class="paragraph"> +<p>(In MyFaces CODI it was originally a CDI interceptor. This part changed +a bit, because between the interceptor and <code>@Secured</code> is the +<code>@SecurityBindingType</code> concept which triggers <code>@Secured</code> as on possible +approach. Therefore the basic behaviour remains the same and you can +think about it like an interceptor.)</p> +</div> +<div class="paragraph"> +<p>The entry point to this API is the <code>@Secured</code> annotation placed either on the whole class — enabling security for all methods — or on individual methods. The only other prerequisite is at least one <code>AccessDecisionVoter</code> implementation, explained in the next section.</p> +</div> +<div class="listingblock"> +<div class="title">Securing All Intercepted Methods of a CDI Bean</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="comment">//...</span> +<span class="annotation">@Secured</span>(CustomAccessDecisionVoter.class) +<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean</span> +{ + <span class="comment">//...</span> +}</code></pre> +</div> +</div> +<div class="listingblock"> +<div class="title">Securing Specific Methods</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="comment">//...</span> +<span class="directive">public</span> <span class="type">class</span> <span class="class">SecuredBean</span> +{ + <span class="annotation">@Secured</span>(CustomAccessDecisionVoter.class) + <span class="directive">public</span> <span class="predefined-type">String</span> getResult() + { + <span class="comment">//...</span> + } +}</code></pre> +</div> +</div> +<div class="sect2"> +<h3 id="_accessdecisionvoter">AccessDecisionVoter</h3> +<div class="paragraph"> +<p>This interface is (besides the <code>@Secured</code> annotation) the most important +part of the concept. Both artifact types are also the only required +parts:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">CustomAccessDecisionVoter</span> <span class="directive">implements</span> AccessDecisionVoter +{ + <span class="annotation">@Override</span> + <span class="directive">public</span> <span class="predefined-type">Set</span><SecurityViolation> checkPermission(AccessDecisionVoterContext accessDecisionVoterContext) + { + <span class="predefined-type">Method</span> method = accessDecisionVoterContext.<InvocationContext>getSource().getMethod(); + + <span class="comment">//...</span> + } +}</code></pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_securityviolation">SecurityViolation</h3> +<div class="paragraph"> +<p>In case of a detected violation a <code>SecurityViolation</code> has to be added to +the result returned by the <code>AccessDecisionVoter</code>.</p> +</div> +</div> +<div class="sect2"> +<h3 id="_abstractaccessdecisionvoter">AbstractAccessDecisionVoter</h3> +<div class="paragraph"> +<p>You can also implement the abstract class <code>AbstractAccessDecisionVoter</code>. +This is a convenience class which allows an easier usage:</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">CustomAccessDecisionVoter</span> <span class="directive">extends</span> AbstractAccessDecisionVoter +{ + + <span class="annotation">@Override</span> + <span class="directive">protected</span> <span class="type">void</span> checkPermission(AccessDecisionVoterContext accessDecisionVoterContext, + <span class="predefined-type">Set</span><SecurityViolation> violations) + { + <span class="comment">// check for violations</span> + violations.add(newSecurityViolation(<span class="string"><span class="delimiter">"</span><span class="content">access not allowed due to ...</span><span class="delimiter">"</span></span>)); + } +}</code></pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="__secured_and_stereotypes_with_custom_metadata">@Secured and stereotypes with custom metadata</h3> +<div class="paragraph"> +<p>If there are multiple <code>AccessDecisionVoter</code> and maybe in different +constellations, it is easier to provide an expressive CDI stereotypes for +it. Later on that also allows to change the behaviour in a central +place.</p> +</div> +<div class="listingblock"> +<div class="title">Stereotype Support of @Secured</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Named</span> +<span class="annotation">@Admin</span> +<span class="directive">public</span> <span class="type">class</span> <span class="class">MyBean</span> <span class="directive">implements</span> <span class="predefined-type">Serializable</span> +{ + <span class="comment">//...</span> +} + +<span class="comment">//...</span> +<span class="annotation">@Stereotype</span> +<span class="annotation">@Secured</span>(RoleAccessDecisionVoter.class) +<span class="directive">public</span> <span class="annotation">@interface</span> Admin +{ +}</code></pre> +</div> +</div> +<div class="paragraph"> +<p>Furthermore, it is possible to provide custom metadata easily.</p> +</div> +<div class="listingblock"> +<div class="title">Stereotype of @Secured with custom metadata</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Named</span> +<span class="annotation">@Admin</span>(securityLevel=<span class="integer">3</span>) +<span class="directive">public</span> <span class="type">class</span> <span class="class">MyBean</span> <span class="directive">implements</span> <span class="predefined-type">Serializable</span> +{ + <span class="comment">//...</span> +} + +<span class="comment">//...</span> +<span class="annotation">@Stereotype</span> +<span class="annotation">@Secured</span>(RoleAccessDecisionVoter.class) +<span class="directive">public</span> <span class="annotation">@interface</span> Admin +{ + <span class="type">int</span> securityLevel(); +} + +<span class="annotation">@ApplicationScoped</span> +<span class="directive">public</span> <span class="type">class</span> <span class="class">RoleAccessDecisionVoter</span> <span class="directive">implements</span> AccessDecisionVoter +{ + <span class="directive">private</span> <span class="directive">static</span> <span class="directive">final</span> <span class="type">long</span> serialVersionUID = -<span class="integer">8007511215776345835L</span>; + + <span class="directive">public</span> <span class="predefined-type">Set</span><SecurityViolation> checkPermission(AccessDecisionVoterContext voterContext) + { + Admin admin = voterContext.getMetaDataFor(Admin.class.getName(), Admin.class); + <span class="type">int</span> level = admin.securityLevel(); + <span class="comment">//...</span> + } +}</code></pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_accessdecisionvotercontext">AccessDecisionVoterContext</h3> +<div class="paragraph"> +<p>Because the <code>AccessDecisionVoter</code> can be chained, +<code>AccessDecisionVoterContext</code> allows to get the current state as well as +the results of the security check.</p> +</div> +<div class="paragraph"> +<p>There are several methods that can be useful</p> +</div> +<div class="ulist"> +<ul> +<li> +<p><code>getState()</code> - Exposes the current state : INITIAL, VOTE_IN_PROGRESS, VIOLATION_FOUND, NO_VIOLATION_FOUND</p> +</li> +<li> +<p><code>getViolations()</code> - Exposes the found violations</p> +</li> +<li> +<p><code>getSource()</code> - Exposes, for example, the current instance of <code>javax.interceptor.InvocationContext</code> in combination with <code>@Secured</code> used as interceptor.</p> +</li> +<li> +<p><code>getMetaData()</code> - Exposes the found meta-data, for example the view-config-class if <code>@Secured</code> is used in combination with type-safe view-configs</p> +</li> +<li> +<p><code>getMetaDataFor(String, Class<T>)</code> - Exposes meta-data for the given key</p> +</li> +</ul> +</div> +</div> +<div class="sect2"> +<h3 id="_securitystrategy_spi">SecurityStrategy SPI</h3> +<div class="paragraph"> +<p>The <code>SecurityStrategy</code> interface allows to provide a custom +implementation which should be used for <code>@Secured</code>. Provide a custom +implementation as bean-class in combination with <code>@Alternative</code> or +<code>@Specializes</code> (or as global-alternative).</p> +</div> +<div class="paragraph"> +<p>In case of global-alternatives an additional configuration needs to be added to +<code>/META-INF/apache-deltaspike.properties</code>.</p> +</div> +<div class="listingblock"> +<div class="title">Example</div> +<div class="content"> +<pre>globalAlternatives.org.apache.deltaspike.security.spi.authorization.SecurityStrategy=mypackage.CustomSecurityStrategy</pre> +</div> +</div> +<div class="admonitionblock tip"> +<table> +<tr> +<td class="icon"> +<i class="fa icon-tip" title="Tip"></i> +</td> +<td class="content"> +The configuration for global alternatives is following the pattern: +<code>globalAlternatives.<em><interface-name></em>=<em><implementation-class-name></em></code> +</td> +</tr> +</table> +</div> +</div> +<div class="sect2"> +<h3 id="_examples">Examples</h3> +<div class="sect3"> +<h4 id="_redirect_to_requested_page_after_login">Redirect to requested page after login</h4> +<div class="paragraph"> +<p>DeltaSpike can be combined with pure CDI or with any other security +frameworks (like PicketLink) to track the denied page and make it +available after user logs in.</p> +</div> +<div class="paragraph"> +<p>An example of this use case is available in the examples module in the DeltaSpike repository:</p> +</div> +<div class="ulist"> +<ul> +<li> +<p><a href="https://github.com/apache/deltaspike/tree/master/deltaspike/examples/security-requested-page-after-login-cdi">Making initially requested secured page available for redirect after login with CDI</a></p> +</li> +<li> +<p><a href="https://github.com/apache/deltaspike/tree/master/deltaspike/examples/security-requested-page-after-login-picketlink">Making initially requested secured page available for redirect after login with PicketLink</a></p> +</li> +</ul> +</div> +<div class="paragraph"> +<p>The relevant classes are <code>AuthenticationListener</code> and <code>LoggedInAccessDecisionVoter</code>.</p> +</div> +</div> +</div> +</div> +</div> + </div> + </div> + + + <div class="span4"> + <div id="toc"> + <div class="moduledeps"> + <ul class="toc-like nav nav-list"> + + <li class="custom-toc-header">Depends on</li> + + <li><a href="core.html">Core</a></li> + + + + + <li class="custom-toc-header">Table of Contents</li> + + </ul> + </div> + </div> + + <div class="fallback-toc"> + <ul class="sectlevel1"> +<li><a href="#_overview">Overview</a></li> +<li><a href="#_project_setup">Project Setup</a> +<ul class="sectlevel2"> +<li><a href="#_1_declare_security_module_dependencies">1. Declare Security Module Dependencies</a></li> +<li><a href="#_2_enable_the_securityinterceptor">2. Enable the SecurityInterceptor</a></li> +</ul> +</li> +<li><a href="#_simple_interceptor_style_authorization">Simple interceptor-style authorization</a></li> +<li><a href="#_advanced_authorization">Advanced authorization</a> +<ul class="sectlevel2"> +<li><a href="#_accessdecisionvoter">AccessDecisionVoter</a></li> +<li><a href="#_securityviolation">SecurityViolation</a></li> +<li><a href="#_abstractaccessdecisionvoter">AbstractAccessDecisionVoter</a></li> +<li><a href="#__secured_and_stereotypes_with_custom_metadata">@Secured and stereotypes with custom metadata</a></li> +<li><a href="#_accessdecisionvotercontext">AccessDecisionVoterContext</a></li> +<li><a href="#_securitystrategy_spi">SecurityStrategy SPI</a></li> +<li><a href="#_examples">Examples</a> +<ul class="sectlevel3"> +<li><a href="#_redirect_to_requested_page_after_login">Redirect to requested page after login</a></li> +</ul> +</li> +</ul> +</li> +</ul> + </div> + + </div> + + + </div> + <div class="row"> + <hr> + <footer> + <p>Copyright © 2011-2016 The Apache Software Foundation, + Licensed under the Apache License, Version 2.0.</p> + + <p>Apache and the Apache feather logo are trademarks of The Apache Software Foundation.</p> + </footer> + </div> +</div> + +</body> </html> \ No newline at end of file
