1、shiro授权角色、权限
新增加俩个查询方法,通过id查询用户所对应的角色,通过id查询用户所对应的权限
<select id="getRolesByUserId" resultType="java.lang.String" parameterType="java.lang.Integer">
select r.roleid from t_shiro_user u,t_shiro_user_role ur,t_shiro_role r
where u.userid = ur.userid and ur.roleid = r.roleid
and u.userid=#{userid}
</select>
<select id="getPersByUserId" resultType="java.lang.String" parameterType="java.lang.Integer">
select p.permission from t_shiro_user u,t_shiro_user_role ur,t_shiro_role_permission rp,t_shiro_permission p
where u.userid = ur.userid and ur.roleid = rp.roleid and rp.perid = p.perid
and u.userid=#{userid}
</select>
Service层就是常规的编写
再重写MyRealm里面的授权方法
package com.zyc.shiro;
import com.zyc.model.ShiroUser;
import com.zyc.service.ShiroUserService;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.stereotype.Component;
import java.util.Set;
/**
* @author 简单定义存在
* @site https://i.csdn.net/#/uc/profile
* @company xxx公司
* @create 2019-11-04 10:32
*/
@Component
public class MyRealm extends AuthorizingRealm {
private ShiroUserService shiroUserService;
public ShiroUserService getShiroUserService() {
return shiroUserService;
}
public void setShiroUserService(ShiroUserService shiroUserService) {
this.shiroUserService = shiroUserService;
}
/**
* 授权的方法
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//从这principalCollection里面拿到要授权的账号
//getPrimaryPrincipal()这个是唯一的身份
String uname=principalCollection.getPrimaryPrincipal().toString();
//拿到当前的用户
ShiroUser shiroUser = this.shiroUserService.querybyName(uname);
//拿到当前用户对应所有权限
Set<String> perids= this.shiroUserService.getPersByUserId(shiroUser.getUserid());
//用户对应的所有角色
Set<String> roleIds= this.shiroUserService.getRolesByUserId(shiroUser.getUserid());
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
//设置角色
info.setRoles(roleIds);
//设置权限
info.setStringPermissions(perids);
//返回AuthorizationInfo
return info;
}
/**
* 认证的方法
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String uname=authenticationToken.getPrincipal().toString();
String pwd=authenticationToken.getCredentials().toString();
ShiroUser shiroUser = shiroUserService.querybyName(uname);
AuthenticationInfo info = new SimpleAuthenticationInfo(
shiroUser.getUsername(),//身份(用户名)
shiroUser.getPassword(),//凭证(密码)
ByteSource.Util.bytes(shiroUser.getSalt()),//凭证盐
this.getName()//数据源名字
);
return info;
}
}
把当前用户对应的所有角色与权限全部给到shiro,由shiro来执行授权的操作
权限规则都在spring与shiro整合的配置文件中:
<?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">
<!--配置自定义的Realm-->
<bean id="shiroRealm" class="com.zyc.shiro.MyRealm">
<property name="shiroUserService" ref="shiroUserService" />
<!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
<!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
<!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
<!--以下三个配置告诉shiro将如何对用户传来的明文密码进行加密-->
<property name="credentialsMatcher">
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--指定hash算法为MD5-->
<property name="hashAlgorithmName" value="md5"/>
<!--指定散列次数为1024次-->
<property name="hashIterations" value="1024"/>
<!--true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储-->
<property name="storedCredentialsHexEncoded" value="true"/>
</bean>
</property>
</bean>
<!--注册安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroRealm" />
</bean>
<!--Shiro核心过滤器-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager" />
<!-- 身份验证失败,跳转到登录页面 -->
<property name="loginUrl" value="/login"/>
<!-- 身份验证成功,跳转到指定页面 -->
<!--<property name="successUrl" value="/index.jsp"/>-->
<!-- 权限验证失败,跳转到指定页面 -->
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<!-- Shiro连接约束配置,即过滤链的定义 -->
<property name="filterChainDefinitions">
<value>
<!--
注:anon,authcBasic,auchc,user是认证过滤器
perms,roles,ssl,rest,port是授权过滤器
-->
<!--anon 表示匿名访问,不需要认证以及授权-->
<!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
<!--roles[admin]表示角色认证,必须是拥有admin角色的用户才行-->
<!--perms["user:update"]表示权限认证,必须是拥有user:update权限的用户才行-->
<!--[]可以为用户或权限名称,也可以为用户或权限id,取决于你的查询方法所查询的内容-->
/user/login=anon
/user/updatePwd.jsp=authc
/admin/*.jsp=roles[admin]
/user/teacher.jsp=perms["user:update"]
<!-- /css/** = anon
/images/** = anon
/js/** = anon
/ = anon
/user/logout = logout
/user/** = anon
/userInfo/** = authc
/dict/** = authc
/console/** = roles[admin]
/** = anon-->
</value>
</property>
</bean>
<!-- Shiro生命周期,保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>
在你登录的时候(subject.login)shiro会先调用认证的方法,再调用授权的方法,这样登录成功之后就可以访问当前用户所拥有的权限了
注意:
在spring整合shiro的配置文件中对凭证(密码)进行了解密的操作,
如果你数据库的密码不是按照配置文件中解密的规则进行加密之后得到的密文的话,
那么解密就不会成功,登录就会失败
运行结果与之前的几乎相同就不演示了
2、Shiro的注解式开发
@RequiresAuthenthentication:表示当前Subject已经通过login进行身份验证;即 Subject.isAuthenticated()返回 true
@RequiresUser:表示当前Subject已经身份验证或者通过记住我登录的
@RequiresGuest:表示当前Subject没有身份验证或者通过记住我登录过,即是游客身份
@RequiresRoles(value = {“admin”,“user”},logical = Logical.AND):表示当前Subject需要角色admin和user
@RequiresPermissions(value = {“user:delete”,“user:b”},logical = Logical.OR):表示当前Subject需要权限user:delete或者user:b
虽然在spring与shiro整合文件中我们配置了安全管理器,但那里的安全管理器只对数据源(MyRealm)进行了管理,我们要使用shiro注解的话还要再springMvc配置文件中配置扫面
shiro注解的安全管理器
<!--扫描shiro的注解-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true"></property>
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!--shiro异常解析器-->
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">
unauthorized
</prop>
</props>
</property>
<property name="defaultErrorView" value="unauthorized"/>
</bean>
测试方法:
@RequiresUser
@ResponseBody
@RequestMapping("/passUser")
public String passUser(){
return "身份认证能够访问";
}
// 角色id为2和(或)4才能访问 AND OR
@RequiresRoles(value = {"2","4"},logical = Logical.OR)
@ResponseBody
@RequestMapping("/passRole")
public String passRole(){
return "角色认证能够访问";
}
// 拥有user:update权限的用户才能访问,可同时填写多个权限 AND 和 OR 或
@RequiresPermissions(value = {"user:update"},logical = Logical.AND)
@ResponseBody
@RequestMapping("/passPer")
public String passPer(){
return "权限认证能够访问";
}
如以上注解规则
passUser:只要认证之后的用户就可以访问;
passRole:角色为2或4的用户可以访问;
passPer:拥有user:update权限的用户才能访问