My technology Stack:
JavaEE6, Glassfish3.1.2.2, Apache Shiro1.2
Steps:
1.) Create a maven projection in addition to include the next dependency.
<dependencies> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.1</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>asm</groupId> <artifactId>asm</artifactId> <version>3.3.1</version> </dependency> <dependency> <groupId>org.jboss.weld</groupId> <artifactId>weld-logger</artifactId> <version>1.0.0-CR2</version> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>6.0</version> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-endorsed-api</artifactId> <version>6.0</version> </dependency> <dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <version>1.1.EDR1.2</version> </dependency> </dependencies>
2.) Create a the shiro ini file: shiro.ini within /src/main/resources folder:
# # Licensed to the Apache Software Foundation (ASF) nether ane # or to a greater extent than contributor license agreements. See the NOTICE file # distributed alongside this operate for additional data # regarding copyright ownership. The ASF licenses this file # to yous nether the Apache License, Version 2.0 (the # "License"); yous may non work this file except inwards compliance # alongside the License. You may obtain a re-create of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required yesteryear applicable police delineate or agreed to inwards writing, # software distributed nether the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either limited or implied. See the License for the # specific linguistic communication governing permissions in addition to limitations # nether the License. # INI configuration is real powerful in addition to flexible, spell even therefore remaining succinct. # Please http://shiro.apache.org/configuration.html in addition to # http://shiro.apache.org/web.html for more. [main] # listener = org.apache.shiro.config.event.LoggingBeanListener shiro.loginUrl = /login.xhtml [users] # format: username = password, role1, role2, ..., roleN origin = secret,admin invitee = guest,guest presidentskroob = 12345,president darkhelmet = ludicrousspeed,darklord,schwartz lonestarr = vespa,goodguy,schwartz [roles] # format: roleName = permission1, permission2, ..., permissionN admin = * schwartz = lightsaber:* goodguy = winnebago:drive:eagle5 [urls] # The /login.jsp is non restricted to authenticated users (otherwise no ane could log in!), only # the 'authc' filter must even therefore live specified for it therefore it tin procedure that url's # login submissions. It is 'smart' plenty to allow those requests through every bit specified yesteryear the # shiro.loginUrl above. /login.xhtml = authc /logout = logout /account/** = authc /remoting/** = authc, roles[b2bClient], perms["remote:invoke:lan,wan"]
3.) In my example I'm exclusively interested alongside RequiresAuthenticated, RequiresRoles in addition to RequiresPermissions, therefore I exclusively implement them. How? Create an interceptor:
package com.czetsuya.commons.web.security.shiro; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.inject.Inject; import javax.interceptor.AroundInvoke; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.authz.Permission; import org.apache.shiro.authz.annotation.RequiresAuthentication; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.permission.WildcardPermission; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Edward P. Legaspi * @since October 10, 2012 */ @Secured @Interceptor populace cast SecurityInterceptor { @Inject someone Subject subject; someone Logger log = LoggerFactory.getLogger(SecurityInterceptor.class); @AroundInvoke populace Object interceptGet(InvocationContext ctx) throws Exception { log.info("Securing {}.{}({})", novel Object[] { ctx.getClass().getName(), ctx.getMethod(), ctx.getParameters() }); terminal Class<? extends Object> runtimeClass = ctx.getTarget().getClass(); // Check if user is authenticated boolean requiresAuthentication = false; seek { // banking concern jibe method commencement ctx.getMethod().getAnnotation(RequiresAuthentication.class); requiresAuthentication = true; } grab (NullPointerException e) { requiresAuthentication = false; } if (!requiresAuthentication) { // banking concern jibe cast score seek { runtimeClass.getAnnotation(RequiresAuthentication.class); requiresAuthentication = true; } grab (NullPointerException e) { requiresAuthentication = false; } } if (requiresAuthentication) { log.debug("[security] checking for authenticated user."); seek { if (!subject.isAuthenticated()) { throw novel AuthorizationException(); } } grab (Exception e) { log.error("Access denied - {}: {}", e.getClass().getName(), e.getMessage()); throw e; } } /************************************************************/ // banking concern jibe if user has roles boolean requiresRoles = false; List<String> listOfRoles = null; seek { // banking concern jibe method commencement RequiresRoles roles = ctx.getMethod().getAnnotation( RequiresRoles.class); listOfRoles = Arrays.asList(roles.value()); requiresRoles = true; } grab (NullPointerException e) { requiresRoles = false; } if (!requiresRoles || listOfRoles == null) { // banking concern jibe cast seek { RequiresRoles roles = runtimeClass .getAnnotation(RequiresRoles.class); listOfRoles = Arrays.asList(roles.value()); requiresRoles = true; } grab (NullPointerException e) { requiresRoles = false; } } if (requiresRoles && listOfRoles != null) { log.debug("[security] checking for roles."); seek { boolean[] boolRoles = subject.hasRoles(listOfRoles); boolean roleVerified = false; for (boolean b : boolRoles) { if (b) { roleVerified = true; break; } } if (!roleVerified) { throw novel AuthorizationException( "Access denied. User doesn't bring plenty privilege Roles:" + listOfRoles + " to access this page."); } } grab (Exception e) { log.error("Access denied - {}: {}", e.getClass().getName(), e.getMessage()); throw e; } } /************************************************************/ // in addition to lastly banking concern jibe for permissions boolean requiresPermissions = false; List<String> listOfPermissionsString = null; seek { // banking concern jibe method commencement RequiresPermissions permissions = ctx.getMethod().getAnnotation( RequiresPermissions.class); listOfPermissionsString = Arrays.asList(permissions.value()); requiresPermissions = true; } grab (NullPointerException e) { requiresPermissions = false; } if (!requiresPermissions || listOfPermissionsString == null) { // banking concern jibe cast seek { RequiresPermissions permissions = runtimeClass .getAnnotation(RequiresPermissions.class); listOfPermissionsString = Arrays.asList(permissions.value()); requiresPermissions = true; } grab (NullPointerException e) { requiresPermissions = false; } } if (requiresPermissions && listOfPermissionsString != null) { log.debug("[security] checking for permissions."); List<Permission> listOfPermissions = novel ArrayList<Permission>(); for (String p : listOfPermissionsString) { listOfPermissions.add((Permission) novel WildcardPermission(p)); } seek { boolean[] boolPermissions = dependent area .isPermitted(listOfPermissions); boolean permitted = false; for (boolean b : boolPermissions) { if (b) { permitted = true; break; } } if (!permitted) { throw novel AuthorizationException( "Access denied. User doesn't bring plenty privilege Permissions:" + listOfRoles + " to access this page."); } } grab (Exception e) { log.error("Access denied - {}: {}", e.getClass().getName(), e.getMessage()); throw e; } } provide ctx.proceed(); } }
3.2) We require JavaEE6 to come across the interceptor yesteryear including it inwards beans.xml (which usually resides inwards /src/main/resources/META-INF of the projection where yous define the interceptor class).
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> <interceptors> <class>com.czetsuya.commons.web.security.shiro.SecurityInterceptor</class> </interceptors> </beans>
4.) We require an interface for interceptor binding:
package com.czetsuya.commons.web.security.shiro; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.interceptor.InterceptorBinding; /** * @author Edward P. Legaspi * @since October 10, 2012 */ @Inherited @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @InterceptorBinding populace @interface Secured { }
5.) Then nosotros require to practice a Singleton cast where nosotros volition instantiate the SecurityManager yesteryear reading the shiro.ini file in addition to hit the Subject in addition to SecurityManager, therefore that nosotros tin inject them afterward if nosotros want.
package com.czetsuya.commons.web.security.shiro; import javax.annotation.PostConstruct; import javax.enterprise.inject.Produces; import javax.inject.Named; import javax.inject.Singleton; import org.apache.shiro.SecurityUtils; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Edward P. Legaspi * @since October 10, 2012 Produces an example of Shiro's dependent area therefore that it tin live * injected. */ @Singleton populace cast SecurityProducer { Logger logger = LoggerFactory.getLogger(SecurityProducer.class); someone SecurityManager securityManager; @PostConstruct populace void init() { terminal String iniFile = "classpath:shiro.ini"; logger.info("Initializing Shiro INI SecurityManager using " + iniFile); securityManager = novel IniSecurityManagerFactory(iniFile).getInstance(); SecurityUtils.setSecurityManager(securityManager); } @Produces @Named("securityManager") populace SecurityManager getSecurityManager() { provide securityManager; } @Produces populace Subject getSubject() { provide SecurityUtils.getSubject(); } }
6.) Sample Usage
package com.czetsuya.mbeans; import javax.ejb.LocalBean; import javax.ejb.Stateless; import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import javax.inject.Inject; import javax.inject.Named; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.annotation.RequiresAuthentication; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import com.czetsuya.commons.web.security.shiro.Secured; /** * @author Edward P. Legaspi * @since October 10, 2012 */ @LocalBean @Named @Stateless populace cast LoginBean { @Inject someone Subject subject; @Inject someone Logger log; someone String username; someone String password; populace String login() { if (subject.isAuthenticated()) { log.debug("[czetsuya-ejbs] active subject={}, user={}", subject, subject.getPrincipal()); provide redirect(); } else { log.debug( "[czetsuya-ejbs] login to the arrangement alongside user={}, password={}", getUsername(), getPassword()); AuthenticationToken token = novel UsernamePasswordToken( getUsername(), getPassword()); seek { subject.login(token); provide redirect(); } grab (Exception e) { log.error("[czetsuya-ejbs] mistake login {}", e); FacesContext.getCurrentInstance().addMessage(null, novel FacesMessage("Error login")); } } provide "home.xhtml"; } populace String logout() { log.debug("[czetsuya-ejbs] logout"); if (subject.isAuthenticated()) { subject.logout(); } FacesContext.getCurrentInstance().addMessage(null, novel FacesMessage("Logout Ok")); provide "login.xhtml"; } someone String redirect() { log.debug("[czetsuya-ejbs] redirect"); if (subject.hasRole("admin")) { provide "admin.xhtml"; } else if (subject.hasRole("schwartz")) { provide "schwartz.xhtml"; } else if (subject.hasRole("goodguy")) { provide "goodguy.xhtml"; } provide "home.xhtml"; } populace String getUsername() { provide username; } populace void setUsername(String username) { this.username = username; } populace String getPassword() { provide password; } populace void setPassword(String password) { this.password = password; } @Secured @RequiresAuthentication populace String requiresAuthentication() { provide ""; } @Secured @RequiresRoles({ "admin" }) populace void requiresRolesMerchant() { log.debug("admin"); } @Secured @RequiresRoles({ "schwartz" }) populace void requiresRolesSupport() { log.debug("schwartz"); } @Secured @RequiresPermissions({ "lightsaber" }) populace void requiresPermissionlightsaber() { log.debug("lightsaber.action"); } @Secured @RequiresPermissions({ "winnebago" }) populace void requiresPermissionSupport() { log.debug("winnebago.action"); } @Secured @RequiresPermissions({ "winnebago", "lightsaber" }) populace void requiresPermissionlightsaberOrwinnebago() { log.debug("winnebago+lightsaber.action"); } }
Related:
Seam Security: https://ngeblognow.blogspot.com//search?q=how-to-setup-seam3-security-in-jboss-7
0 komentar:
Please comment if there are any that need to be asked.