blob: 2008cbd9b7c9eb4d29622ea3adf5503250b74d6f [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>Java Authorization Guide with Apache Shiro | Apache Shiro</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="keywords" content='documentation,manual'>
<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="Java Authorization Guide with 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='documentation'/>
<meta property="article:tag" content='manual'/>
<meta property="og:locale" content="en_US" />
<meta property="og:url" content='https://shiro.apache.org/java-authorization-guide.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>Java Authorization Guide with Apache Shiro</h1>
</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>Authorization, or access control, is the function of specifying access rights to resources. In other words, <em>who</em> has access to <em>what</em>.</p>
</div>
<div class="paragraph">
<p>Examples of authorization checks are: Is the user allowed to look at this webpage, edit this data, view this button, or print to this printer? Those are all decisions determining what a user has access to.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="elements_of_authorization">Elements of Authorization</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Authorization has three core elements that we reference quite a bit in Shiro– permissions, roles, and users.</p>
</div>
<div class="sect2">
<h3 id="permissions_defined">Permissions Defined</h3>
<div class="paragraph">
<p>Permissions are the most atomic level of a security policy, and they are statements of functionality. Permissions represent what can be done in your application. A well-formed permission describes a resource types and what actions are possible when you interact with those resources. Can you <em>open</em> a <em>door</em>? Can you <em>read</em> a <em>file</em>? Can you <em>delete</em> a <em>customer record</em>? Can you <em>push</em> a <em>button</em>?</p>
</div>
<div class="paragraph">
<p>Common actions for data-related resources are create, read, update, and delete, commonly referred to as CRUD.</p>
</div>
<div class="paragraph">
<p>It is important to understand that permissions do not have knowledge of <em>who</em> can perform the actions– they are just statements of <em>what</em> actions can be performed.</p>
</div>
<div class="sect3">
<h4 id="levels_of_permission_granularity">Levels of permission granularity</h4>
<div class="paragraph">
<p>The permissions above all specify an actions (open, read, delete, etc.) on a resource (door, file, customer record, etc). In Shiro, you can define a permission to any depth you like. Here are a few common permission levels in order of granularity.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Resource Level - This is the broadest and easiest to build. A user can edit customer records or open doors. The resource is specified but not a specific instance of that resource.</p>
</li>
<li>
<p>Instance Level - The permission specifies the instance of a resource. A user can edit the customer record for IBM or open the kitchen door.</p>
</li>
<li>
<p>Attribute Level - The permission now specifies an attribute of an instance or resource. A user can edit the address on the IBM customer record.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For more information on Permissions please check out the <a href="permissions.html">Permissions Documentation</a></p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="roles_defined">Roles Defined</h3>
<div class="paragraph">
<p>In the context of Authorization, Roles are effectively a collection of permissions used to simplify the management of permissions and users. So users can be assigned roles instead of being assigned permissions directly, which can get complicated with larger user bases and more complex applications. So, for example, a bank application might have an <em>administrator</em> role or a <em>bank teller</em> role.</p>
</div>
<div class="paragraph">
<p>There are two types of roles that you need to be aware of and Shiro will support both.</p>
</div>
<div class="sect3">
<h4 id="implicit_roles">Implicit Roles</h4>
<div class="paragraph">
<p>Most people view roles as what we define as an implicit role where your application <em>implies</em> a set of permissions because a user has a particular role as opposed to the role explicitly being assigned permissions or your application checking for those permissions. Role checks in code are generally a reflection of an implicit role. You can view patient data because you have the <em>administrator</em> role. You can create an account because you have the <em>bank teller</em> role. The fact that these names exist does not have a correlation to what the software can actually do. Most people use roles in this manner. It is easiest, but it can create a lot of maintenance and management problems for all but the simplest application.</p>
</div>
</div>
<div class="sect3">
<h4 id="explicit_roles">Explicit Roles</h4>
<div class="paragraph">
<p>An explicit role has permissions <em>explicitly</em> assigned to it and therefore is an <em>explicit</em> collection of permissions. Permission checks in code are a reflection of an explicit role. You can view patient data because you have the <em>view patient data</em> permission as part of your <em>administrator</em> role. You can create an account because you have the <em>create account</em> permission as part of your <em>bank teller</em> role. You can perform these actions, not because of some implicit role name based on a string but because the corresponding permission was explicitly assigned to your role.</p>
</div>
<div class="paragraph">
<p>The big benefits of explicit roles are easier manageability and lower maintenance of your application. If you ever need to add, remove, or change a role, you can do so without touching your source code. And in Shiro, you&#8217;ll also be able to dynamically add, remove, or change roles at runtime and your authorization checks will always have up-to-date values. This means you won&#8217;t have to force users to log out and log back in order to get their new permissions.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="users_defined">Users Defined</h3>
<div class="paragraph">
<p>A user is the "who" of an application. In Shiro, though, the concept of a user is really the <a href="subject.html">Subject</a> instance. We use word Subject instead of user because user usually implies a human being and in Shiro a Subject can be anything interacting with your application– whether it be a human or a service.</p>
</div>
<div class="paragraph">
<p>Users are allowed to perform certain actions in your application through their association with roles or direct permissions. So you are able to open a customer record because you&#8217;ve been assigned the <em>open customer record</em> permission, either through a role you&#8217;ve been assigned or through a direct permission assignment.</p>
</div>
<div class="paragraph">
<p>For more information on Users, aka Subjects, please check out the <a href="subject.html">Subject Documentation</a>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<div class="title">Note</div>
<p>Ultimately, your <a href="realm.html">Realm</a> implementation is what communicates with your data source (RDBMS, LDAP, etc). So your realm is what will tell Shiro whether roles or permissions exist. You have full control over how your authorization model works.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="how_to_perform_authorization_in_java_with_shiro">How to perform Authorization in Java with Shiro</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Authorization in Shiro can be handled in four ways.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Programmatically - You can perform authorization checks in your java code with structures like <code>if</code> and <code>else</code> blocks.</p>
</li>
<li>
<p>JDK annotations - You can attach an authorization annotation to your Java methods</p>
</li>
<li>
<p>JSP/GSP TagLibs - You can control jsp or gsp page output based on roles and permissions</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="programmatic_authorization">Programmatic Authorization</h3>
<div class="paragraph">
<p>Checking for permissions and roles, programmatically in your Java code is the traditional way of handling authorization. Here&#8217;s how you can perform a permission check or role check in Shiro.</p>
</div>
<div class="sect3">
<h4 id="role_check">Role Check</h4>
<div class="paragraph">
<p>This is an example of how you do a role check programmatically in your application. We want to check if a user has the <em>administrator</em> role and if they do, then we&#8217;ll show a special button, otherwise we won&#8217;t show it.SubjectAwareExecutor.html#execute(java.lang.Runnable)</p>
</div>
<div class="paragraph">
<p>First we get access to the current user, the <a href="subject.html">Subject</a>. Then we pass the <em>administrator</em> to the Subject&#8217;s <a href="static/current/apidocs/org/apache/shiro/subject/Subject.html#hasRole(java.lang.String)"><code>.hasRole()</code></a> method. It will return <code>TRUE</code> or <code>FALSE</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//get the current Subject
Subject currentUser = SecurityUtils.getSubject();
if (currentUser.hasRole("administrator")) {
//show a special button‏
} else {
//don’t show the button?)‏
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now a role based check is quick and easy to implement, but it has a major drawback. It is implicit.</p>
</div>
<div class="paragraph">
<p>What if you just want to add, remove, or redefine a role later? You&#8217;ll have to crack open your source code and change all your role checks to reflect the change in your security model. You&#8217;ll have to shut down the application, crack open the code, test it, and then restart it everytime.</p>
</div>
<div class="paragraph">
<p>In very simple applications this is probably good enough but for larger apps this can be a major problem throughout the life of your application and drive a large maintenance cost for your software.</p>
</div>
</div>
<div class="sect3">
<h4 id="permission_check">Permission Check</h4>
<div class="paragraph">
<p>This is an example of how you do security checks by permission. We want to check if a user has permission to print to laserjet3000n and if they do, then we&#8217;ll show a print button, otherwise we won&#8217;t show it. This is an example of an instance level permission or instance level authorization.</p>
</div>
<div class="paragraph">
<p>Again, first you get access to the current user, the <a href="subject.html">Subject</a>. Then you construct a <a href="static/current/apidocs/org/apache/shiro/authz/Permission.html"><code>Permission</code></a> object or an instance that represents an action on a resource. In this case, the instance is named <code>printerPermission</code>, the resource is <em>laserjet3000n</em>, and the action is <em>print</em>. Then we pass <code>printerPermission</code> to the Subject&#8217;s <a href="static/current/apidocs/org/apache/shiro/subject/Subject.html#isPermitted(java.util.List)"><code>.isPermitted()</code></a> method. It will return true or false.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Subject currentUser = SecurityUtils.getSubject();
Permission printPermission = new PrinterPermission("laserjet3000n","print");
If (currentUser.isPermitted(printPermission)) {
//do one thing (show the print button?)‏
} else {
//don’t show the button?
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="permission_check_string_based">Permission Check (String-based)</h4>
<div class="paragraph">
<p>You can also a permission check using a simple string instead of a permission class.</p>
</div>
<div class="paragraph">
<p>So, if you don&#8217;t want to implement our <a href="static/current/apidocs/org/apache/shiro/authz/Permission.html">permission interface</a> then you just pass in a String. In this example, we pass the <code>.isPermitted()</code> method a string, <code>printer:print:LaserJet4400n</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">String perm = "printer:print:laserjet4400n";
if(currentUser.isPermitted(perm)){
//show the print button?
} else {
//don’t show the button?
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can construct the permission string the way you want so long as your <a href="realm.html">Realm</a> knows how to work with it. In this example we use Shiro&#8217;s optional permission syntax, <a href="permissions.html">WildCardPermissions</a>. WildCardPermissions are powerful and intuitive. If you&#8217;d like to learn more about them then check out the <a href="static/current/apidocs/org/apache/shiro/authz/Permission.html">Permissions Documentation</a>.</p>
</div>
<div class="paragraph">
<p>With string-based permission checks, you get the same functionality as the example before. The benefit is that you are not forced to implement a permission interface, and you can construct the permission via a simple string. The downside is that you don&#8217;t have type safety and if you needed more complicated permission capabilities that are outside the scope of what this represents, you&#8217;re going to want to implement your own permission objects based on the permission interface.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="annotation_authorization">Annotation Authorization</h3>
<div class="paragraph">
<p>If you don&#8217;t want to do code level authorization checks, then you can use Java Annotations as well. Shiro offers a number of <a href="java-annotations-list.html">Java annotations</a> that allow you to annotate methods.</p>
</div>
<div class="sect3">
<h4 id="enabling_annotation_support">Enabling Annotation Support</h4>
<div class="paragraph">
<p>Before you can use Java annotations, you&#8217;ll need to enable AOP support in your application. There are a number of different AOP frameworks so, unfortunately, there is no standard way to enable AOP in an application.</p>
</div>
<div class="paragraph">
<p>For AspectJ, you can review our <a href="https://github.com/apache/shiro/tree/main/samples/aspectj">AspectJ sample application</a>.</p>
</div>
<div class="paragraph">
<p>For Spring, you can look into our <a href="spring-framework.html">Spring Integration</a> documentation.</p>
</div>
<div class="paragraph">
<p>For Guice, you can look into our <a href="guice.html">Guice Integration</a> documentation.</p>
</div>
</div>
<div class="sect3">
<h4 id="permission_check_2">Permission Check</h4>
<div class="paragraph">
<p>In this example, we want to check that a user has the <code>account:create</code> permission before they can invoke the <code>openAccount</code> method. If they do, then the method is called as expected, and if they don&#8217;t, then an exception is thrown.</p>
</div>
<div class="paragraph">
<p>Like programmatic checks, you can use the <a href="static/current/apidocs/org/apache/shiro/authz/Permission.html">Permission</a> objects or the simple string methods with this annotation.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//Will throw an AuthorizationException if none
//of the caller’s roles imply the Account
//'create' permission
@RequiresPermissions("account:create")
public void openAccount( Account acct ) {
//create the account
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="role_check_2">Role Check</h4>
<div class="paragraph">
<p>In this example, we want to check that a user has the <code>teller</code> role before they can invoke the <code>openAccount</code> method. If they do, then the method is called as expected, and if they don&#8217;t, then an exception is thrown.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">//Throws an AuthorizationException if the caller
//doesn’t have the ‘teller’ role:
@RequiresRoles( "teller" )
public void openAccount( Account acct ) {
//do something in here that only a teller
//should do
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="jsp_taglib_authorization">JSP TagLib Authorization</h3>
<div class="paragraph">
<p>For JSP/GSP based web applications, Shiro also offers a <a href="jsp-tag-library.html">tag library</a> for you to use.</p>
</div>
<div class="paragraph">
<p>In this example, we&#8217;re going to show users with the <em>users:manage</em> permission a link to the Manage Users page. If they do not have the permission, then we&#8217;ll show them a nice message.</p>
</div>
<div class="paragraph">
<p>First, we&#8217;ll need to add the Shiro taglib to our web application. Next, we add the <code>&lt;shiro:hasPermission&gt;</code> tag with a check for <em>users:manage</em>. Within the <code>&lt;shiro:hasPermission&gt;</code> tags we will place the code we want to execute if the user has the permission we&#8217;re checking for. If we want to take an action if the user lacks the permission, then we need to also add the <code>&lt;shiro:lacksPermission&gt;</code> tag, again checking for <em>users:manage</em>. And any code we want to execute if the user lacks the permission will need to be placed within the <code>&lt;shiro:lacksPermission&gt;</code> tags.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html">&lt;%@ taglib prefix="shiro" uri=http://shiro.apache.org/tags %&gt;
&lt;html&gt;
&lt;body&gt;
&lt;shiro:hasPermission name="users:manage"&gt;
&lt;a href="manageUsers.jsp"&gt;
Click here to manage users
&lt;/a&gt;
&lt;/shiro:hasPermission&gt;
&lt;shiro:lacksPermission name="users:manage"&gt;
No user management for you!
&lt;/shiro:lacksPermission&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Of course, there also tags for checking roles and other user data and states.</p>
</div>
<div class="paragraph">
<p>For more information on JSP/GSP Tags please check out the <a href="jsp-tag-library.html">JSP Tag Library</a> and for more information on integration your application in your web application, please read the <a href="web.html">Web Integration Documentation</a></p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="caching_authorization">Caching Authorization</h2>
<div class="sectionbody">
<div class="paragraph">
<p>TBD</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/java-authorization-guide.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>