Shiro简单入门+个人理解(3)

最后一天,对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" onclick="selectChannel(this)" id="menu_4"><a onfocus="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 注解修饰的类为全局异常处理类
*/
@ControllerAdvice
public 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

}

 因为公司的的原因使用了两种方式,但都属于此类,请理解编写

 

posted @ 2019-02-18 10:22  只待时光静好  阅读(289)  评论(0编辑  收藏  举报