最后一天,对shiro框架的应用也到此为至了,可能不是太全,但相对于一般的项目,它的作用已经使用了很多了
Shiro的授权:
授权:对用户资源访问的授权(是否允许用户访问此资源)
用户访问系统资源时的授权流程如下:
1)系统调用subject相关方法将用户信息(例如isPermitted)递交给SecurityManager
2)SecurityManager将权限检测操作委托给Authorizer对象
3)Authorizer将用户信息委托给realm.
4)Realm访问数据库获取用户权限信息并封装。
5) Authorizer对用户授权信息进行判定。
自定义realm(重点)
@Service
public class ShiroUserRealm extends AuthorizingRealm {//AuthenticatingRealm (提供了认证数据的获取方法)//同样省略dao //自定义缓存map(缓存用户权限信息) private Map<String,SimpleAuthorizationInfo> authorMap= new ConcurrentHashMap<String,SimpleAuthorizationInfo>(); /**此方法提供认证数据的获取操作*/ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { System.out.println("==获取用户认证信息=="); //1.获取用户名(从令牌对象获取) UsernamePasswordToken upToken= (UsernamePasswordToken)token; String username=upToken.getUsername();// String username=(String)token.getPrincipal();// System.out.println("username="+username); //2.基于用户名执行查询操作获取用户对象 User user=sysUserDao.findUserByUserName(username); //3.对用户对象进行判定 //3.1判定用户是否存在 if(user==null){ throw new UnknownAccountException(); } //3.2密码验证 //4.对用户相关信息进行封装(密码) SimpleAuthenticationInfo info=new SimpleAuthenticationInfo( user,//principal (用户新身份) user.getUSER_PWD(),//hashedCredentials(已加密的凭证) getName());//realmName real name //5.返回封装好的数据(返回给认证管理器) return info;//交给认证管理器 } /** *此方法提供授权数据的获取操作,当我们访问系统中的一个需要 *授权访问的方法时,shiro框架底层会通过如下方法获取用户权限 *信息. */ @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { //1.获取登录用户信息(用户身份对象) User user=(User)principals.getPrimaryPrincipal(); if(authorMap.containsKey(user.getUSER_NAME())) return authorMap.get(user.getUSER_NAME()); System.out.println("==获取用户权限信息==="); //2.获取用户具备的权限信息 //2.1 根据用户id获取用户拥有的角色 System.out.println("......."); System.out.println(user.getUSER_I()); List<Integer> roleIds= sysUserRoleDao.findRoleIdsByUserId(user.getUSER_I()); if(roleIds==null||roleIds.size()==0){ throw new AuthorizationException("您无权访问"); } System.out.println("第一次测试"); //2.2.基于角色id获取角色对应的菜单id List<Integer> menuIds= sysRoleMenuDao.findMenuIdsByRoleId( roleIds.toArray(new Integer[]{})); if(menuIds==null||menuIds.size()==0){ throw new AuthorizationException("您无权访问"); } System.out.println("第二次测试"); //2.3.基于菜单id获取菜单表中定义的权限标识(权限)` List<String> permissions= sysMenuDao.findPermissions(menuIds.toArray(new Integer[]{})); System.out.println("第三次测试"); //3.封装用户权限信息 Set<String> permissionSet=new HashSet<String>(); for(String per:permissions){ if(!StringUtils.isEmpty(per)){ permissionSet.add(per); }//去重,去空(null,"") } SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); info.setStringPermissions(permissionSet); //4.返回封装结果 authorMap.put(user.getUSER_NAME(), info); return info; }}在需要进行授权检测的方法上添加执行此方法需要的权限标识
例如
注解方式
@RequestPermissions(“interface:getInterfaceConfig”)
xml配置方式
<entry key="/company/deleteCompany.do" value="perms[company:delete]" /> -->
jsp方式
<shiro:hasPermission name="xtgl:userList">
<li class="top_menu" οnclick="selectChannel(this)" id="menu_4"><a οnfοcus="this.blur();" hidefocus="true"><span><img src="images/icon/nav_icon2.png" /></span><p>用户管理</p></a></li> </shiro:hasPermission>标识都是存在数据库里(依靠查询判断)
在realm有抛出异常的可能所以为大家提供全局异常类
package com.cn.ericsson.controler;
import java.util.List;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.LockedAccountException;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authz.AuthorizationException;import org.springframework.web.bind.annotation.ControllerAdvice;/** * @ControllerAdvice注解修饰的类为spring mvc中的全局异常处理类 */import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import com.cn.ericsson.util.AppUtil;
import com.cn.ericsson.util.PageData;import com.cn.ericsson.util.json.ClientJsonUtil; /** * @ControllerAdvice 注解修饰的类为全局异常处理类 */@ControllerAdvicepublic class GlobalExceptionHandler { @ExceptionHandler(ShiroException.class) @ResponseBody public Object doShiroException( ShiroException exp){ exp.printStackTrace();//控制台输出 //System.out.println("asdfasdfasdfasdfasdfasdfasdfasfasdfasdfasdfasdfasdfasdfasdf"+exp); // JsonResult r=new JsonResult(); //r.setState(0);//exception Object item=null; String data = null; List list=null; /* * String data = ClientJsonUtil.assembleJson("查询成功", ClientJsonUtil.STATUS_200,list); item = AppUtil.returnJsonpObject(new PageData(), data.toLowerCase()); * * */ if(exp instanceof UnknownAccountException){ // r.setMessage("用户名不存在"); data = ClientJsonUtil.assembleJson("用户不存在",ClientJsonUtil.STATUS_201,list); item=AppUtil.returnJsonpObject(new PageData(), data.toLowerCase()); }else if(exp instanceof LockedAccountException){ // r.setMessage("用户已被禁用"); data = ClientJsonUtil.assembleJson("用户被禁用",ClientJsonUtil.STATUS_201,list); item=AppUtil.returnJsonpObject(new PageData(), data.toLowerCase()); }else if(exp instanceof IncorrectCredentialsException){ // r.setMessage("密码不正确"); data = ClientJsonUtil.assembleJson("密码错误",ClientJsonUtil.STATUS_201); item=AppUtil.returnJsonpObject(new PageData(), data); }else if(exp instanceof AuthorizationException){ //r.setMessage("没有此权限"); data = ClientJsonUtil.assembleJson("没有此权限",ClientJsonUtil.STATUS_201,list); item=AppUtil.returnJsonpObject(new PageData(), data.toLowerCase()); }else{ //r.setMessage(exp.getMessage()); data = ClientJsonUtil.assembleJson("未知错误",ClientJsonUtil.STATUS_201,list); item=AppUtil.returnJsonpObject(new PageData(), data.toLowerCase()); } return item; } /** * @ExceptionHandler 注解描述的方法为一个异常处理 * 方法 * @param e * @return 封装了异常信息的JsonResult对象 */ @ExceptionHandler(RuntimeException.class) @ResponseBody public JsonResult doHandleRuntimeException( RuntimeException e){ e.printStackTrace(); return new JsonResult(e); }//jackson}因为公司的的原因使用了两种方式,但都属于此类,请理解编写