• 008-shiro与spring web项目整合【二】认证、授权、session管理


    一、认证

    1、添加凭证匹配器

    添加凭证匹配器实现md5加密校验。

    修改applicationContext-shiro.xml:

        <!-- realm -->
        <bean id="customRealm" class="com.lhx.ssm.shiro.CustomRealm">
            <!-- 将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列 -->
            <property name="credentialsMatcher" ref="credentialsMatcher"/>
        </bean>
    
        <!-- 凭证匹配器 -->
        <bean id="credentialsMatcher"
              class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
            <property name="hashAlgorithmName" value="md5"/>
            <property name="hashIterations" value="1"/>
        </bean>
    View Code

    2、修改realm认证方法

    修改realm代码从数据库中查询用户身份信息,将sysService注入realm。

    public class CustomRealm extends AuthorizingRealm {
        
        //注入service
        @Autowired
        private SysService sysService;
    
        // 设置realm的名称
        @Override
        public void setName(String name) {
            super.setName("customRealm");
        }
        // 支持什么类型的token
        @Override
        public boolean supports(AuthenticationToken token) {
            return token instanceof UsernamePasswordToken;
        }
    
        // 用于认证    
        //realm的认证方法,从数据库查询用户信息
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(
                AuthenticationToken token) throws AuthenticationException {
            
            // token是用户输入的用户名和密码 
            // 第一步从token中取出用户名
            String userCode = (String) token.getPrincipal();
    
            // 第二步:根据用户输入的userCode从数据库查询
            SysUser sysUser = null;
            try {
                sysUser = sysService.findSysUserByUserCode(userCode);
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
    
            // 如果查询不到返回null
            if(sysUser==null){//
                return null;
            }
            // 从数据库查询到密码
            String password = sysUser.getPassword();
            
            //
            String salt = sysUser.getSalt();
    
            // 如果查询到返回认证信息AuthenticationInfo
            
            //activeUser就是用户身份信息
            ActiveUser activeUser = new ActiveUser();
            
            activeUser.setUserid(sysUser.getId());
            activeUser.setUsercode(sysUser.getUsercode());
            activeUser.setUsername(sysUser.getUsername());
            //..
            
            //根据用户id取出菜单
            List<SysPermission> menus  = null;
            try {
                //通过service取出菜单 
                menus = sysService.findMenuListByUserId(sysUser.getId());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //将用户菜单 设置到activeUser
            activeUser.setMenus(menus);
    
            //将activeUser设置simpleAuthenticationInfo
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                    activeUser, password,ByteSource.Util.bytes(salt), this.getName());
    
            return simpleAuthenticationInfo;
        }
            // ……授权下一个
    }    
        
    View Code

    二、授权

    1.修改realm授权方法

    修改realm代码从数据库中查询权限信息,将sysService注入realm

    public class CustomRealm extends AuthorizingRealm {
        
        //注入service
        @Autowired
        private SysService sysService;
    
        // 设置realm的名称
        @Override
        public void setName(String name) {
            super.setName("customRealm");
        }
        // 支持什么类型的token
        @Override
        public boolean supports(AuthenticationToken token) {
            return token instanceof UsernamePasswordToken;
        }
    
        // 用于认证    
        //realm的认证方法,从数据库查询用户信息
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(
                AuthenticationToken token) throws AuthenticationException {
            
            // token是用户输入的用户名和密码 
            // 第一步从token中取出用户名
            String userCode = (String) token.getPrincipal();
    
            // 第二步:根据用户输入的userCode从数据库查询
            SysUser sysUser = null;
            try {
                sysUser = sysService.findSysUserByUserCode(userCode);
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
    
            // 如果查询不到返回null
            if(sysUser==null){//
                return null;
            }
            // 从数据库查询到密码
            String password = sysUser.getPassword();
            
            //
            String salt = sysUser.getSalt();
    
            // 如果查询到返回认证信息AuthenticationInfo
            
            //activeUser就是用户身份信息
            ActiveUser activeUser = new ActiveUser();
            
            activeUser.setUserid(sysUser.getId());
            activeUser.setUsercode(sysUser.getUsercode());
            activeUser.setUsername(sysUser.getUsername());
            //..
            
            //根据用户id取出菜单
            List<SysPermission> menus  = null;
            try {
                //通过service取出菜单 
                menus = sysService.findMenuListByUserId(sysUser.getId());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //将用户菜单 设置到activeUser
            activeUser.setMenus(menus);
    
            //将activeUser设置simpleAuthenticationInfo
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                    activeUser, password,ByteSource.Util.bytes(salt), this.getName());
    
            return simpleAuthenticationInfo;
        }
        
        
    
        // 用于授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(
                PrincipalCollection principals) {
            
            //从 principals获取主身份信息
            //将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型),
            ActiveUser activeUser =  (ActiveUser) principals.getPrimaryPrincipal();
            
            //根据身份信息获取权限信息
            //从数据库获取到权限数据
            List<SysPermission> permissionList = null;
            try {
                permissionList = sysService.findPermissionListByUserId(activeUser.getUserid());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //单独定一个集合对象 
            List<String> permissions = new ArrayList<String>();
            if(permissionList!=null){
                for(SysPermission sysPermission:permissionList){
                    //将数据库中的权限标签 符放入集合
                    permissions.add(sysPermission.getPercode());
                }
            }
            
            
        /*    List<String> permissions = new ArrayList<String>();
            permissions.add("user:create");//用户的创建
            permissions.add("item:query");//商品查询权限
            permissions.add("item:add");//商品添加权限
            permissions.add("item:edit");//商品修改权限
    */        //....
            
            //查到权限数据,返回授权信息(要包括 上边的permissions)
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            //将上边查询到授权信息填充到simpleAuthorizationInfo对象中
            simpleAuthorizationInfo.addStringPermissions(permissions);
    
            return simpleAuthorizationInfo;
        }    
    }
    View Code

    2、对controller开启aop

    在springmvc.xml中配置shiro注解支持,可在controller方法中使用shiro注解配置权限:

        <!-- 开启aop,对类代理 -->
        <aop:config proxy-target-class="true"></aop:config>
        <!-- 开启shiro注解支持 -->
        <bean
            class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager" />
        </bean>

    3、权限注解控制

    商品查询controller方法添加权限(item:query):

        // 查询商品列表
        @RequestMapping("/queryItem")
        @RequiresPermissions("item:query")
        public ModelAndView queryItem() throws Exception {

    上边代码@RequiresPermissions("item:query")表示必须拥有“item:query”权限方可执行。

    同理,商品修改controller方法添加权限(item:update):

        @RequestMapping(value = "/editItem")
        @RequiresPermissions("item:update")
        public String editItem(@RequestParam(value = "id", required = true) Integer id, Model model) throws Exception

    商品提交

        // 商品修改提交
        @RequestMapping("/editItemSubmit")
        @RequiresPermissions("item:update")
        public String editItemSubmit(@ModelAttribute("item") Items items,BindingResult result,MultipartFile pictureFile,Model model,HttpServletRequest request)
                throws Exception

    4、jsp标签控制

    4.1、标签简介

    a、Jsp页面添加:

    <%@ tagliburi="http://shiro.apache.org/tags" prefix="shiro" %>

     b、详细

    标签名称

    标签条件(均是显示标签内容)

    <shiro:authenticated>

    登录之后

    <shiro:notAuthenticated>

    不在登录状态时

    <shiro:guest>

    用户在没有RememberMe时

    <shiro:user>

    用户在RememberMe时

    <shiro:hasAnyRoles name="abc,123" >

    在有abc或者123角色时

    <shiro:hasRole name="abc">

    拥有角色abc

    <shiro:lacksRole name="abc">

    没有角色abc

    <shiro:hasPermission name="abc">

    拥有权限资源abc

    <shiro:lacksPermission name="abc">

    没有abc权限资源

    <shiro:principal>

    显示用户身份名称

     <shiro:principal property="username"/>     显示用户身份中的属性值

     4.2、jsp页面添加标签

    如果有商品修改权限页面显示“修改”链接。

    <shiro:hasPermission name="item:update">
        <a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a>
    </shiro:hasPermission>

     三、session管理

    和shiro整合后,使用shiro的session管理,shiro提供sessionDao操作 会话数据。

        <!-- securityManager安全管理器 -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="customRealm"/>
            <!-- 注入session管理器 -->
            <property name="sessionManager" ref="sessionManager"/>
        </bean>
        <!-- 会话管理器 -->
        <bean id="sessionManager"          class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
            <!-- session的失效时长,单位毫秒 -->
            <property name="globalSessionTimeout" value="600000"/>
            <!-- 删除失效的session -->
            <property name="deleteInvalidSessions" value="true"/>
        </bean>
  • 相关阅读:
    博客园-随笔分类批量修改
    【读书笔记】--少有人走的路①:心智成熟的旅程
    自定义菜单用例
    自定义菜单创建接口
    发送消息---被动回复用户消息
    接收消息----接收语音识别结果
    接收消息----接收事件推送
    微信开发入门教程
    Hadoop维护IPC链接
    Hadoop建立IPC连接和数据读写
  • 原文地址:https://www.cnblogs.com/bjlhx/p/7420724.html
Copyright © 2020-2023  润新知