first implementation of JSF 2.2 shiro faces tag lib

This commit is contained in:
jomu
2016-07-08 11:16:18 +00:00
parent b411b6aff9
commit c2458139b3
18 changed files with 867 additions and 0 deletions

43
shiro-faces/pom.xml Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.muehlencord.shared</groupId>
<artifactId>shared-shiro-faces</artifactId>
<packaging>jar</packaging>
<name>shared-shiro-faces</name>
<parent>
<groupId>de.muehlencord</groupId>
<artifactId>shared</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<properties>
<shiro.version>1.2.6</shiro.version>
<elapi.version>3.0.0</elapi.version>
<jsfapi.version>2.2.13</jsfapi.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>${jsfapi.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>${elapi.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,51 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.el.ValueExpression;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagAttribute;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public abstract class AbstractAccessControlTag extends AbstractTag {
protected TagAttribute attribute;
public AbstractAccessControlTag(TagConfig config) {
super(config);
}
protected String getAttributeValue(FaceletContext ctx, TagAttribute attr) {
String value;
if (attr.isLiteral()) {
value = attr.getValue(ctx);
} else {
ValueExpression expression = attr.getValueExpression(ctx, String.class);
value = (String) expression.getValue(ctx);
}
return value;
}
protected boolean isPermitted(String permission) {
return getSubject() != null && getSubject().isPermitted(permission);
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public abstract class AbstractAuthenticationTag extends AbstractTag {
protected AbstractAuthenticationTag(TagConfig config) {
super(config);
}
protected abstract boolean isAuthenticated();
protected boolean applyTagHandler() {
if (isAuthenticated()) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Authentication verified, tag will be evaluated");
}
return true;
} else {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace ("Authentifaction verification failed, tag will not be evaluated");
}
return false;
}
}
@Override
public void apply(FaceletContext fc, UIComponent uic) throws IOException {
if (applyTagHandler()) {
this.nextHandler.apply(fc, uic);
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public abstract class AbstractPermissionTag extends AbstractAccessControlTag {
protected AbstractPermissionTag(TagConfig config) {
super(config);
this.attribute = this.getRequiredAttribute("name");
}
protected abstract boolean hasPermission(String permission);
@Override
protected boolean isPermitted(String permission) {
return getSubject() != null && getSubject().isPermitted(permission);
}
@Override
public void apply(FaceletContext fc, UIComponent uic) throws IOException {
String permissionName = getAttributeValue(fc, attribute);
if (hasPermission(permissionName)) {
this.nextHandler.apply(fc, uic);
}
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public abstract class AbstractRoleTag extends AbstractAccessControlTag {
protected AbstractRoleTag(TagConfig config) {
super(config);
this.attribute = this.getRequiredAttribute("name");
}
protected abstract boolean hasRole(String role);
public void apply(FaceletContext fc, UIComponent uic) throws IOException {
String roleName = getAttributeValue(fc, attribute);
if (hasRole(roleName)) {
this.nextHandler.apply(fc, uic);
}
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.faces.view.facelets.TagConfig;
import javax.faces.view.facelets.TagHandler;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public abstract class AbstractTag extends TagHandler {
protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractTag.class);
public AbstractTag(TagConfig config) {
super(config);
}
protected Subject getSubject() {
return SecurityUtils.getSubject();
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlencord.de>
*/
public class AuthenticatedTag extends AbstractAuthenticationTag {
public AuthenticatedTag(TagConfig config) {
super(config);
}
@Override
protected boolean isAuthenticated() {
return getSubject() != null && getSubject().isAuthenticated();
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class GuestTag extends AbstractAuthenticationTag {
public GuestTag(TagConfig config) {
super(config);
}
@Override
protected boolean isAuthenticated() {
return getSubject() == null || getSubject().getPrincipal() == null;
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import java.util.Arrays;
import java.util.List;
import javax.faces.view.facelets.TagConfig;
import org.apache.shiro.subject.Subject;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class HasAnyPermissionTag extends AbstractPermissionTag {
private final static String PERMISSIONS_DELIMETER = ",";
public HasAnyPermissionTag(TagConfig config) {
super(config);
}
@Override
protected boolean hasPermission(String permissions) {
Subject subject = getSubject();
if (subject != null) {
List<String> permissionsList = Arrays.asList(permissions.split(PERMISSIONS_DELIMETER));
return permissionsList.stream().anyMatch(permission -> subject.isPermitted(permission));
} else return false;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import java.util.Arrays;
import java.util.List;
import javax.faces.view.facelets.TagConfig;
import org.apache.shiro.subject.Subject;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class HasAnyRolesTag extends AbstractRoleTag {
private final static String ROLE_NAMES_DELIMETER = ",";
public HasAnyRolesTag(TagConfig config) {
super(config);
}
@Override
protected boolean hasRole(String roleNames) {
Subject subject = getSubject();
if (subject != null) {
List<String> roleList = Arrays.asList(roleNames.split(ROLE_NAMES_DELIMETER));
return roleList.stream().anyMatch(role -> subject.hasRole(role.trim()));
}
return false;
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class HasPermissionTag extends AbstractPermissionTag {
public HasPermissionTag(TagConfig config) {
super(config);
}
@Override
protected boolean hasPermission(String permission) {
return isPermitted(permission);
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class HasRoleTag extends AbstractRoleTag {
public HasRoleTag(TagConfig config) {
super(config);
}
@Override
protected boolean hasRole(String role) {
return getSubject() != null && getSubject().hasRole(role);
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class LacksPermissionTag extends AbstractPermissionTag {
public LacksPermissionTag(TagConfig config) {
super(config);
}
@Override
protected boolean hasPermission(String permission) {
return !isPermitted(permission);
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class LacksRoleTag extends AbstractRoleTag {
public LacksRoleTag(TagConfig config) {
super(config);
}
@Override
protected boolean hasRole(String role) {
return getSubject() != null && getSubject().hasRole(role);
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class NotAuthenticatedTag extends AbstractAuthenticationTag {
public NotAuthenticatedTag(TagConfig config) {
super(config);
}
@Override
protected boolean isAuthenticated() {
return getSubject() == null || !getSubject().isAuthenticated();
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags;
import javax.faces.view.facelets.TagConfig;
/**
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class UserTag extends AbstractAuthenticationTag {
public UserTag(TagConfig config) {
super(config);
}
@Override
protected boolean isAuthenticated() {
return getSubject() != null && getSubject().getPrincipal() != null;
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
*
* Licensed 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.
*/
package de.muehlencord.shirofaces.tags.unsupported;
import de.muehlencord.shirofaces.tags.AbstractTag;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagConfig;
/**
* <p>
* Tag used to print out the String value of a user's default principal, or a
* specific principal as specified by the tag's attributes.</p>
*
* <p>
* If no attributes are specified, the tag prints out the <tt>toString()</tt>
* value of the user's default principal. If the <tt>type</tt> attribute is
* specified, the tag looks for a principal with the given type. If the
* <tt>property</tt> attribute is specified, the tag prints the string value of
* the specified property of the principal. If no principal is found or the user
* is not authenticated, the tag displays nothing unless a <tt>defaultValue</tt>
* is specified.</p>
*
* @author Joern Muehlencord <joern at muehlenocrd.de>
*/
public class PrincipalTag extends AbstractTag {
public PrincipalTag(TagConfig config) {
super(config);
}
@Override
public void apply(FaceletContext fc, UIComponent uic) throws IOException {
throw new UnsupportedOperationException("PrincipalTag Not supported yet.");
}
}

View File

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
Licensed 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.
-->
<facelet-taglib version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facelettaglibrary_2_2.xsd">
<namespace>http://shiro.apache.org/tags</namespace>
<tags>
<tag>
<tag-name>authenticated</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.AuthenticatedTag</handler-class>
<description>Displays body content only if the current user has successfully authenticated
_during their current session_. It is more restrictive than the 'user' tag.
It is logically opposite to the 'notAuthenticated' tag.
</description>
</tag>
<tag>
<tag-name>guest</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.GuestTag</handler-class>
<description>Displays body content only if the current Subject IS NOT known to the system, either
because they have not logged in or they have no corresponding 'RememberMe' identity. It is logically
opposite to the 'user' tag.
</description>
</tag>
<tag>
<tag-name>hasAnyPermission</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.HasAnyPermissionTag</handler-class>
<description>Displays body content only if the current user has one of the specified permissions from a comma-separated list of permissions.</description>
<attribute>
<description>comma-separated list of permissions to check for</description>
<name>name</name>
<required>true</required>
</attribute>
</tag>
<tag>
<tag-name>hasAnyRoles</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.HasAnyRolesTag</handler-class>
<description>Displays body content only if the current user has one of the specified roles from a comma-separated list of role names.</description>
<attribute>
<description>comma-separated list of roles to check for</description>
<name>name</name>
<required>true</required>
</attribute>
</tag>
<tag>
<tag-name>hasPermission</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.HasPermissionTag</handler-class>
<description>Displays body content only if the current user the given permission.</description>
<attribute>
<description>the permission to check for</description>
<name>name</name>
<required>true</required>
</attribute>
</tag>
<tag>
<tag-name>hasRole</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.HasRoleTag</handler-class>
<description>Displays body content only if the current user has the given role.</description>
<attribute>
<description>the role to check for</description>
<name>name</name>
<required>true</required>
</attribute>
</tag>
<tag>
<tag-name>lacksPermission</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.LacksPermissionTag</handler-class>
<description>Displays body content only if the current user has NOT the given permission.</description>
<attribute>
<description>the permission to check for</description>
<name>name</name>
<required>true</required>
</attribute>
</tag>
<tag>
<tag-name>lacksRole</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.LacksRoleTag</handler-class>
<description>Displays body content only if the current user has NOT the given role.</description>
<attribute>
<description>the role to check for</description>
<name>name</name>
<required>true</required>
</attribute>
</tag>
<tag>
<tag-name>hasRole</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.HasRoleTag</handler-class>
<attribute>
<description>the name of the role to check for</description>
<name>name</name>
<required>true</required>
</attribute>
</tag>
<tag>
<tag-name>notAuthenticated</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.NotAuthenticatedTag</handler-class>
<description>Displays body content only if the current user has NOT succesfully authenticated
_during their current session_. It is logically opposite to the 'authenticated' tag.
</description>
</tag>
<tag>
<tag-name>user</tag-name>
<handler-class>de.muehlencord.shirofaces.tags.UserTag</handler-class>
<description>Displays body content only if the current Subject has a known identity, either
from a previous login or from 'RememberMe' services. Note that this is semantically different
from the 'authenticated' tag, which is more restrictive. It is logically
opposite to the 'guest' tag.
</description>
</tag>
</tags>
</facelet-taglib>