Shiro
搭建
-
pom.xml: 导入库
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency> <!--缓存包--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.4.0</version> </dependency> <!--核心包--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version> </dependency>
-
web.xml: 过滤器
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
xml: bean设置
- anno,任何人都可以访问;
- authc:必须是登录之后才能进行访问,不包括remember me;
- user:登录用户才可以访问,包含remember me;
- perms:指定过滤规则,这个一般是扩展使用,不会使用原生的
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 授权 认证 --> <bean id="jdbcRealm" class="controller.UserRealm"></bean> <!-- Shiro安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="jdbcRealm"></property> </bean> //id必须与过滤器名称一致 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"></property> <property name="loginUrl" value="/login.html"></property> <property name="successUrl" value="/index"></property> <!-- 用户访问未对其授权的资源时,所显示的连接 --> <property name="unauthorizedUrl" value="/unauthorizedUrl"></property> <property name="filterChainDefinitions"> <value> /inlogin=anon /test/**=roles[role1] /index=authc </value> </property> </bean> </beans>
-
Realm实现
package controller; import java.util.HashSet; import java.util.Set; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component public class UserRealm extends AuthorizingRealm { protected Logger logger = LoggerFactory.getLogger(this.getClass()); @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) { UsernamePasswordToken token = (UsernamePasswordToken) SecurityUtils.getSubject().getPrincipal(); String username = token.getUsername(); logger.info(username + "授权..."); // 从数据库中查找该用户的角色和权限 SimpleAuthorizationInfo sainfo = new SimpleAuthorizationInfo(); Set<String> roles = new HashSet<String>(); roles.add("admin"); //roles.add("role1"); Set<String> permissions = new HashSet<String>(); permissions.add("add"); permissions.add("delete"); sainfo.setRoles(roles); sainfo.setStringPermissions(permissions); return sainfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) arg0; String username = token.getUsername(); // 根据username从数据库查找用户,得到密码 // 假设找到的用户如下 // User user = userService.findByUsername(username) // if (null == user) // { // throw new AccountException("username is not exist"); // } // else if (!user.getPassword().equals(new String(token.getPassword()))) // { // throw new AccountException("password is not right"); // } // else // { // 登陆成功 logger.info("{} login success.", username); // } return new SimpleAuthenticationInfo(arg0, "21232f297a57a5a743894a0e4a801fc3", username); } }
登录验证
- 验证
Subject sub = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
sub.login(token);
- 退出登录
sub.logout();
- 获取session:
sub.getsession();
权限检验
-
xml属性
<property name="filterChainDefinitions"> <value> /callback=anon /=authc /**=anon </value> </property>
-
annotation
-
@RequiresAuthentication
验证用户是否登录,等同于方法subject.isAuthenticated() 结果为true时。 -
@RequiresUser
验证用户是否被记忆,user有两种含义- 一种是成功登录的(subject.isAuthenticated() 结果为true);
- 另外一种是被记忆的(subject.isRemembered()结果为true)。
-
@RequiresGuest
验证是否是一个guest的请求,与@RequiresUser完全相反。
换言之,RequiresUser == !RequiresGuest。
此时subject.getPrincipal() 结果为null. -
@RequiresRoles
@RequiresRoles("aRoleName"); void someMethod();
如果subject中有aRoleName角色才可以访问方法someMethod。如果没有这个权限则会抛出异常AuthorizationException。
-
@RequiresPermissions
@RequiresPermissions({"file:read", "write:aFile.txt"} ) void someMethod();
要求subject中必须同时含有file:read和write:aFile.txt的权限才能执行方法someMethod()
-
-
tag标签
-
<shiro:guest> 游客访问 <a href = "login.jsp"></a> </shiro:guest>
-
user 标签:用户已经通过认证\记住我 登录后显示响应的内容
<shiro:user> 欢迎[<shiro:principal/>]; 登录 <a href = "logout">; 退出</a> </shiro:user>
-
authenticated标签:用户身份验证通过,即 Subjec.login 登录成功 不是记住我登录的
<shiro:authenticted> 用户[<shiro:principal/>] 已身份验证通过 </shiro:authenticted>
-
notAuthenticated标签:用户未进行身份验证,即没有调用Subject.login进行登录,包括"记住我"也属于未进行身份验证
<shiro:notAuthenticated> 未身份验证(包括"记住我") </shiro:notAuthenticated>
-
principal 标签:显示用户身份信息,默认调用
Subjec.getPrincipal()获取,即Primary Principal <shiro:principal property = "username"/>
-
hasRole标签:如果当前Subject有角色将显示body体内的内容
<shiro:hashRole name = "admin"> 用户[<shiro:principal/>] 拥有角色admin </shiro:hashRole>
-
hasAnyRoles标签:如果Subject有任意一个角色(或的关系)将显示body体里的内容
<shiro:hasAnyRoles name = "admin,user"> 用户[<shiro:pricipal/>]拥有角色admin 或者 user </shiro:hasAnyRoles>
-
lacksRole:如果当前 Subjec没有角色将显示body体内的内容
<shiro:lacksRole name = "admin"> 用户[<shiro:pricipal/>]没有角色admin </shiro:lacksRole>
-
hashPermission:如果当前Subject有权限将显示body体内容
<shiro:hashPermission name ="user:create"> 用户[<shiro:pricipal/>] 拥有权限user:create </shiro:hashPermission>
-
lacksPermission:如果当前Subject没有权限将显示body体内容
<shiro:lacksPermission name = "org:create"> 用户[<shiro:pricipal/>] 没有权限org:create </shiro:lacksPermission>
-
-
指定权限
Subject currentUser = SecurityUtils.getSubject(); if (currentUser.hasRole("admin")) { logger.info("-----------啊啊啊啊--admin---------"); } if (currentUser.hasRole("user")) { logger.info("-----------user---------"); }
注解支持
<!-- 开启shiro的注解支持 -->
<bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<!-- 必须改为true,即使用cglib方式为Action创建代理对象。默认值为false,使用JDK创建代理对象,会造成问题 -->
<property name="proxyTargetClass" value="true"></property>
</bean>
<!-- 使用shiro框架提供的切面类,用于创建代理对象 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"></bean>
无权限时转接
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">/mg/unauthorized</prop>
</props>
</property>
</bean>