008-shiro与spring web项目整合认证授权session管理

Posted 木子旭

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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>

 

以上是关于008-shiro与spring web项目整合认证授权session管理的主要内容,如果未能解决你的问题,请参考以下文章

spring boot整合mybitas怎么配置oracle?

Spring整合web项目原理以及IOC与DI关系

007-shiro与spring web项目整合基础搭建

Spring:概述,IOC(Bean管理),整合Web项目,整合JUnit单元测试

010-shiro与spring web项目整合缓存EhcacheRedis

009-shiro与spring web项目整合验证码记住我