blob: cabe6ad1ad76712fe8f13b83f58d01a469480c78 [file] [log] [blame]
<!DOCTYPE html>
<!--
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.
-->
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Understanding Permissions in Apache Shiro | Apache Shiro</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="keywords" content='permissions,authorization'>
<meta name="generator" content="JBake">
<meta name="google-site-verification" content="QIax6uT5UX3enoU0G8Pz2pXbQ45KaQuHZ3nCh9V27mw">
<meta name="google-site-verification" content="ecFap6dWJgS_GCCtxmJQJ_nFYQhM6EgSpBPZDU7xsCE">
<meta name="google-site-verification" content="gBTYOG8lMfNb_jrWrH3kFbudpEs_WrAJ2lb2-zLRaso"/>
<meta name="msvalidate.01" content="0B57EB46CBFAD8FD45008D2DB6B6C68C">
<meta property="og:title" content="Understanding Permissions in Apache Shiro | Apache Shiro"/>
<meta property="og:type" content="article"/>
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@ApacheShiro" />
<meta property="article:modification_time" content="2010-03-18T00:00:00Z"/>
<meta property="article:tag" content='permissions'/>
<meta property="article:tag" content='authorization'/>
<meta property="og:locale" content="en_US" />
<meta property="og:url" content='https://shiro.apache.org/permissions.html'/>
<meta property="og:image" content='images/shiro-featured-image.png'/>
<meta property="og:image:width" content='1200'/>
<meta property="og:image:height" content='628'/>
<meta property="og:site_name" content="Apache Shiro"/>
<!-- Le styles -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="bootstrap-icons-1.5.0/bootstrap-icons.css" rel="stylesheet">
<link href="css/asciidoctor.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<link href="highlight.js-11.2.0/styles/default.min.css" rel="stylesheet">
<link href="css/gh-pages/gh-fork-ribbon.css" rel="stylesheet"/>
<!-- Fav and touch icons -->
<!--<link rel="apple-touch-icon-precomposed" sizes="144x144" href="../assets/ico/apple-touch-icon-144-precomposed.png">
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="../assets/ico/apple-touch-icon-114-precomposed.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="../assets/ico/apple-touch-icon-72-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="../assets/ico/apple-touch-icon-57-precomposed.png">-->
<link rel="shortcut icon" href="favicon.ico">
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//matomo.privacy.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '2']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body>
<div id="top-bar"></div>
<a class="github-fork-ribbon right-top" href="https://github.com/apache/shiro" title="Fork me on GitHub">Fork me on GitHub</a>
<div id="wrap">
<div class="masthead">
<p class="lead">
<a href="index.html"><img src="images/apache-shiro-logo.png" style="height:100px; width:auto; vertical-align: bottom; margin-top: 20px;" alt="Apache Shiro Logo"></a>
<span class="tagline">Simple. Java. Security.</span>
<a class="pull-right" href="https://www.apache.org/events/current-event.html">
<img style="padding-top: 8px" src="https://www.apache.org/events/current-event-125x125.png" alt="Apache Software Foundation Event Banner"/>
</a>
</p>
</div>
<!-- Fixed navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light shadow-sm mb-4">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="get-started.html">Get Started</a>
</li>
<li class="nav-item">
<a class="nav-link" href="documentation.html">Docs</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown-webapps" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Web Apps
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown-webapps">
<li><a class="dropdown-item" href="web.html">General</a></li>
<li><a class="dropdown-item" href="jaxrs.html">JAX-RS</a></li>
<li><a class="dropdown-item" href="jakarta-ee.html">Jakarta EE</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="web-features.html">Features</a></li>
</ul>
</li>
<li><a class="nav-link" href="features.html">Features</a></li>
<!-- integrations -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown-integrations" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Integrations
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown-integrations">
<li><a class="dropdown-item" href="spring-boot.html">Spring</a></li>
<li><a class="dropdown-item" href="guice.html">Guice</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="integration.html">Third-Party Integrations</a></li>
</ul>
</li>
<!-- Community -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown-community" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Community
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown-community">
<li><a class="dropdown-item" href="forums.html">Community Forums</a></li>
<li><a class="dropdown-item" href="mailing-lists.html">Mailing Lists</a></li>
<li><a class="dropdown-item" href="articles.html">Articles</a></li>
<li><a class="dropdown-item" href="news.html">News</a></li>
<li><a class="dropdown-item" href="events.html">Events</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="community.html">More</a></li>
</ul>
</li>
<!-- About -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown-about" role="button" data-bs-toggle="dropdown" aria-expanded="false">
About
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown-about">
<li><a class="dropdown-item" href="about.html">About</a></li>
<li><a class="dropdown-item" href="privacy-policy.html">Privacy Policy</a></li>
<li><a class="dropdown-item" href="security-reports.html">Vulnerability Reports</a></li>
</ul>
</li>
</ul>
<ul class="d-flex justify-content-end navbar-nav mb-2 mb-lg-0">
<!-- The ASF -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown-asf" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Apache Software Foundation
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown-asf">
<li><a class="dropdown-item" href="https://www.apache.org/">Apache Homepage</a></li>
<li><a class="dropdown-item" href="https://www.apache.org/licenses/">License</a></li>
<li><a class="dropdown-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a class="dropdown-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
<li><a class="dropdown-item" href="https://www.apache.org/security/">Security</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<div class="page-header">
<h1>Understanding Permissions in Apache Shiro</h1>
</div>
<div class="related-content">
<h2>Related Content</h2>
<h3 class="title"><a href="java-authorization-guide.html">Java Authorization Guide with Apache Shiro</a></h3>
<p class="description">
</p>
<p>
<span class="read-more"><a href="java-authorization-guide.html">Read More &gt;&gt;</a></span>
</p>
<h3 class="title"><a href="webapp-tutorial.html">Securing Web Applications with Apache Shiro</a></h3>
<p class="description">
</p>
<p>
<span class="read-more"><a href="webapp-tutorial.html">Read More &gt;&gt;</a></span>
</p>
<h3 class="title"><a href="get-started.html">Get Started with Apache Shiro</a></h3>
<p class="description">
</p>
<p>
<span class="read-more"><a href="get-started.html">Read More &gt;&gt;</a></span>
</p>
<h3 class="title"><a href="10-minute-tutorial.html">10 Minute Tutorial on Apache Shiro</a></h3>
<p class="description">
Try Apache Shiro for yourself in under 10 minutes.
</p>
<p>
<span class="read-more"><a href="10-minute-tutorial.html">Read More &gt;&gt;</a></span>
</p>
</div>
<div class="admonitionblock tip">
<table>
<tbody>
<tr>
<td class="icon">
<div class="title">Handy Hint</div>
</td>
<td class="content">
<div class="title">Shiro v1 version notice</div>
<div class="paragraph">
<p>As of 2024-02-28, Shiro v1 will soon be superseded by v2.<p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Shiro defines a Permission as a statement that defines an explicit behavior or action. It is a statement of raw functionality in an application and nothing more. Permissions are the lowest-level constructs in security polices, and they explicitly define only "what" the application can do.</p>
</div>
<div class="paragraph">
<p>They do <em>not</em> at all describe "who" is able to perform the action(s).</p>
</div>
<div class="paragraph">
<p>Some examples of permissions:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Open a file</p>
</li>
<li>
<p>View the '/user/list' web page</p>
</li>
<li>
<p>Print documents</p>
</li>
<li>
<p>Delete the 'jsmith' user</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Defining "who" (users) is allowed to do "what" (permissions) is an exercise of assigning permissions to users in some way. This is always done by the application&#8217;s data model and can vary greatly across applications.</p>
</div>
<div class="paragraph">
<p>For example, permissions can be grouped in a Role and that Role could be associated with one or more User objects. Or some applications can have a Group of users and a Group can be assigned a Role, which by transitive association would mean that all the Users in that Group are implicitly granted the permissions in the Role.</p>
</div>
<div class="paragraph">
<p>There are many variations for how permissions could be granted to users - the application determines how to model this based on the application requirements.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="wildcard_permissions">Wildcard Permissions</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The above examples of permissions, "Open a file", "View the 'user/list' web page", etc. are all valid permission statements.However, it would be very difficult computationally to interpret those natural language strings and determine if a user is allowed to perform that behavior or not.</p>
</div>
<div class="paragraph">
<p>So to enable easy-to-process yet still readable permission statements, Shiro provides powerful and intuitive permission syntax we refer to as the WildcardPermission.</p>
</div>
<div class="sect2">
<h3 id="simple_usage">Simple Usage</h3>
<div class="paragraph">
<p>Let&#8217;s say you want to protect access to your company&#8217;s printers such that some people can print to particular printers, while others can query what jobs are currently in the queue.</p>
</div>
<div class="paragraph">
<p>An extremely simple approach would be to grant the user a "queryPrinter" permission.Then you could check to see if the user has the queryPrinter permission by calling:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">subject.isPermitted("queryPrinter")</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is (mostly) equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">subject.isPermitted( new WildcardPermission("queryPrinter") )</code></pre>
</div>
</div>
<div class="paragraph">
<p>but more on that later.</p>
</div>
<div class="paragraph">
<p>The simple permission string may work for simple applications, but it requires you to have permissions like "printPrinter", "queryPrinter", "managePrinter", etc. You can also grant a user &quot;*&quot; permissions using the wildcard character (giving this permission construct its name), which means they have <strong><em>all</em></strong> permissions across <em>the entire application</em>.</p>
</div>
<div class="paragraph">
<p>But using this approach there&#8217;s no way to just say a user has "all printer permissions". For this reason, Wildcard Permissions supports multiple <em>levels</em> of permissioning.</p>
</div>
</div>
<div class="sect2">
<h3 id="multiple_parts">Multiple Parts</h3>
<div class="paragraph">
<p>Wildcard Permissions support the concept of multiple <em>levels</em> or <em>parts</em>. For example, you could restructure the previous simple example by granting a user the permission</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:query</code></pre>
</div>
</div>
<div class="paragraph">
<p>The colon in this example is a special character used to delimit the next part in the permission string.</p>
</div>
<div class="paragraph">
<p>In this example, the first part is the domain that is being operated on (<code>printer</code>) and the second part is the action (<code>query</code>) being performed. The other above examples would be changed to:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:print
printer:manage</code></pre>
</div>
</div>
<div class="paragraph">
<p>There is no limit to the number of parts that can be used, so it is up to your imagination in terms of ways that this could be used in your application.</p>
</div>
<div class="sect3">
<h4 id="multiple_values">Multiple Values</h4>
<div class="paragraph">
<p>Each part can contain multiple values. So instead of granting the user both the "printer:print" and "printer:query" permissions, you could simply grant them one:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:print,query</code></pre>
</div>
</div>
<div class="paragraph">
<p>which gives them the ability to <code>print</code> and <code>query</code> printers. And since they are granted both those actions, you could check to see if the user has the ability to query printers by calling:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">subject.isPermitted("printer:query")</code></pre>
</div>
</div>
<div class="paragraph">
<p>which would return <code>true</code></p>
</div>
</div>
<div class="sect3">
<h4 id="all_values">All Values</h4>
<div class="paragraph">
<p>What if you wanted to grant a user <em>all</em> values in a particular part? It would be more convenient to do this than to have to manually list every value. Again, based on the wildcard character, we can do this. If the <code>printer</code> domain had 3 possible actions (<code>query</code>, <code>print</code>, and <code>manage</code>), this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:query,print,manage</code></pre>
</div>
</div>
<div class="paragraph">
<p>simply becomes this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:*</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then, <em>any</em> permission check for "printer:XXX" will return <code>true</code>. Using the wildcard in this way scales better than explicitly listing actions since, if you added a new action to the application later, you don&#8217;t need to update the permissions that use the wildcard character in that part.</p>
</div>
<div class="paragraph">
<p>Finally, it is also possible to use the wildcard token in any part of a wildcard permission string. For example, if you wanted to grant a user the "view" action across <em>all</em> domains (not just printers), you could grant this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">*:view</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then any permission check for "foo:view" would return <code>true</code></p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="instance_level_access_control">Instance-Level Access Control</h3>
<div class="paragraph">
<p>Another common usage of wildcard permissions is to model instance-level Access Control Lists. In this scenario you use three parts - the first is the <em>domain</em>, the second is the <em>action</em>(s), and the third is the instance(s) being acted upon.</p>
</div>
<div class="paragraph">
<p>So for example you could have</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:query:lp7200
printer:print:epsoncolor</code></pre>
</div>
</div>
<div class="paragraph">
<p>The first defines the behavior to <code>query</code> the <code>printer</code> with the ID <code>lp7200</code>. The second permission defines the behavior to <code>print</code> to the <code>printer</code> with ID <code>epsoncolor</code>. If you grant these permissions to users, then they can perform specific behavior on <em>specific instances</em>. Then you can do a check in code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if ( SecurityUtils.getSubject().isPermitted("printer:query:lp7200") {
// Return the current jobs on printer lp7200 }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is an extremely powerful way to express permissions. But again, having to define multiple instance IDs for all printers does not scale well, particularly when new printers are added to the system. You can instead use a wildcard:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:print:*</code></pre>
</div>
</div>
<div class="paragraph">
<p>This does scale, because it covers any new printers as well. You could even allow access to all actions on all printers:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:*:*</code></pre>
</div>
</div>
<div class="paragraph">
<p>or all actions on a single printer:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:*:lp7200</code></pre>
</div>
</div>
<div class="paragraph">
<p>or even specific actions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:query,print:lp7200</code></pre>
</div>
</div>
<div class="paragraph">
<p>The '*' wildcard and ',' sub-part separator can be used in any part of the permission.</p>
</div>
<div class="sect3">
<h4 id="missing_parts">Missing Parts</h4>
<div class="paragraph">
<p>One final thing to note about permission assignments: missing parts imply that the user has access to all values corresponding to that part. In other words,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:print</code></pre>
</div>
</div>
<div class="paragraph">
<p>is equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:print:*</code></pre>
</div>
</div>
<div class="paragraph">
<p>and</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer</code></pre>
</div>
</div>
<div class="paragraph">
<p>is equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:*:*</code></pre>
</div>
</div>
<div class="paragraph">
<p>However, you can only leave off parts from the <em>end</em> of the string, so this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:lp7200</code></pre>
</div>
</div>
<div class="paragraph">
<p>is <strong><em>not</em></strong> equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:*:lp7200</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="checking_permissions">Checking Permissions</h2>
<div class="sectionbody">
<div class="paragraph">
<p>While permission assignments use the wildcard construct quite a bit ("printer:print:*" = print to any printer) for convenience and scalability, permission <strong>checks</strong> at runtime should <em>always</em> be based on the most specific permission string possible.</p>
</div>
<div class="paragraph">
<p>For example, if the user had a UI, and they wanted to print a document to the <code>lp7200</code> printer, you <strong>should</strong> check if the user is permitted to do so by executing this code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if ( SecurityUtils.getSubject().isPermitted("printer:print:lp7200") ) {
//print the document to the lp7200 printer }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>That check is very specific and explicitly reflects what the user is attempting to do at that moment in time.</p>
</div>
<div class="paragraph">
<p>The following however is much less ideal for a runtime check:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">if ( SecurityUtils.getSubject().isPermitted("printer:print") ) {
//print the document }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Why? Because the second example says "You must be able to print to <strong>any</strong> printer for the following code block to execute". But remember that "printer:print" is equivalent to "printer:print:*"!</p>
</div>
<div class="paragraph">
<p>Therefore, this is an incorrect check. What if the current user does not have the ability to print to any printer, but they <strong>do</strong> have the ability to print to say, the <code>lp7200</code> and <code>epsoncolor</code> printers. Then the 2nd example above would never allow them to print to the <code>lp7200</code> printer even though they have been granted that ability!</p>
</div>
<div class="paragraph">
<p>So the rule of thumb is to use the most specific permission string possible when performing permission checks. Of course, the 2nd block above might be a valid check somewhere else in the application if you really did only want to execute the code block if the user was allowed to print to any printer (suspect, but possible). Your application will determine what checks make sense, but in general, the more specific, the better.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="implication_not_equality">Implication, not Equality</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Why is it that runtime permission checks should be as specific as possible, but permission assignments can be a little more generic? It is because the permission checks are evaluated by <em>implication</em> logic - not equality checks.</p>
</div>
<div class="paragraph">
<p>That is, if a user is assigned the <code>user:*</code> permission, this <em>implies</em> that the user can perform the <code>user:view</code> action. The string "user:*" is clearly not equal to "user:view", but the former implies the latter. "user:*" describes a superset of functionality of that defined by "user:view".</p>
</div>
<div class="paragraph">
<p>To support implication rules, all permissions are translated in to object instances that implement the <code>org.apache.shiro.authz.Permission</code> interface. This is so that implication logic can be executed at runtime and that implication logic is often more complex than a simple string equality check. All the wildcard behavior described in this document is actually made possible by the <code>org.apache.shiro.authz.permission.WildcardPermission</code> class implementation. Here are some more wildcard permission strings that show access by implication:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">user:*</code></pre>
</div>
</div>
<div class="paragraph">
<p><em>implies</em> the ability to also delete a user:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">user:delete</code></pre>
</div>
</div>
<div class="paragraph">
<p>Similarly,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">user:*:12345</code></pre>
</div>
</div>
<div class="paragraph">
<p><em>implies</em> the ability to also update user account with ID 12345:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">user:update:12345</code></pre>
</div>
</div>
<div class="paragraph">
<p>and</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer</code></pre>
</div>
</div>
<div class="paragraph">
<p><em>implies</em> the ability to print to any printer</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">printer:print</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="performance_considerations">Performance Considerations</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Permission checks are more complex than a simple equals comparison, so runtime implication logic must execute for each assigned Permission. When using permission strings like the ones shown above, you&#8217;re implicitly using Shiro&#8217;s default <code>WildcardPermission</code> which executes the necessary implication logic.</p>
</div>
<div class="paragraph">
<p>Shiro&#8217;s default behavior for Realm implementations is that, for every permission check (for example, a call to <code>subject.isPermitted</code>), <em>all</em> of the permissions assigned to that user (in their Groups, Roles, or directly assigned to them) need to be checked individually for implication. Shiro 'short circuits' this process by returning immediately after the first successful check occurs to increase performance, but it is not a silver bullet.</p>
</div>
<div class="paragraph">
<p>This is usually extremely fast when users, roles and permissions are cached in memory when using a proper <a href="cachemanager.html">CacheManager</a>, which Shiro does support for Realm implementations. Just know that with this default behavior, as the number of permissions assigned to a user or their roles or groups increase, the time to perform the check will necessarily increase.</p>
</div>
<div class="paragraph">
<p>If a Realm implementor has a more efficient way of checking permissions and performing this implication logic, especially if based on the application&#8217;s data model, they should implement that as part of their Realm isPermitted* method implementations. The default Realm/WildcardPermission support exists to cover 80-90% of most use cases, but it might not be the best solution for applications that have massive amounts of permissions to store and/or check at runtime.</p>
</div>
</div>
</div>
<hr />
</div>
<div class="footer-padding"></div>
<div class="container-fluid pt-2 border-top" id="custom-footer">
<footer class="row justify-content-between align-items-center">
<div class=" col-md-5">
<div class="copyright-footer justify-content-start">
<a href="https://www.apache.org/foundation/contributing.html">Donate to the ASF</a>&nbsp;|&nbsp;
<a href="https://www.apache.org/licenses/LICENSE-2.0.html">License</a>&nbsp;
<p class="text-muted">Copyright &copy; 2008-2024 The Apache Software Foundation</p>
</div>
</div>
<div class="d-flex justify-content-center col-md-1">
<a class="btn btn-social"><span class="social-icon social-twitter"><i class="bi bi-twitter"></i></span></a>
<a class="btn btn-social"><span class="social-icon social-facebook"><i class="bi bi-facebook"></i></span></a>
<a class="btn btn-social"><span class="social-icon social-linkedin"><i class="bi bi-linkedin"></i></span></a>
</div>
<div class="d-flex justify-content-end col-md-4" id="editThisPage">
<input type="hidden" id="ghEditPage" value="https://github.com/apache/shiro-site/edit/main/src/site/content/permissions.adoc"/>
</div>
<div class="d-flex col-md-2 justify-content-end" style="position: relative">
<div class="footer-shield"></div>
</div>
</footer>
</div>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="js/bootstrap.min.js"></script>
<script src="highlight.js-11.2.0/highlight.min.js"></script>
<script src="js/shiro.js"></script>
<script>
docReady(
addPageEditLink()
);
</script>
<script>hljs.highlightAll();</script>
</body>
</html>