maven+ssm+eclipse整合shiro

1.在pom中加入shiro依赖

2.在spring配置文件同级目录下创建一个shiro的配置文件spring-shiro.xml 内容如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    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-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    
    
    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <!-- 开启Shiro注解 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
    depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager"/>
    </bean>
     <!-- 配置自定义Realm 你自己写的ShiroSecurityRealm类继承了shiro的AuthorizingRealm类-->
    <bean id="myRealm" class="com.wx.security.ShiroSecurityRealm">
        <property name="credentialsMatcher">
        <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
            <!-- 加密算法 -->
            <property name="hashAlgorithmName" value="MD5"></property>
            <!-- 加密次数 -->
            <property name="hashIterations" value="1024"></property>
        </bean>
    </property>
    </bean>
    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="myRealm"/>
    </bean>
    <!-- Shiro过滤器 核心-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <!-- Shiro的核心安全接口,这个属性是必须的 -->
    <property name="securityManager" ref="securityManager"/>
    <!-- 身份认证失败,则跳转到登录页面的配置 -->
    <property name="loginUrl" value="/views/login.jsp"/>
    <!-- 权限认证失败,则跳转到指定页面 -->
    <property name="unauthorizedUrl" value="/page/toFail"/>
    <!-- Shiro连接约束配置,即过滤链的定义 -->
    <property name="filterChainDefinitions">
    <value>
    <!--anon 表示匿名访问,不需要认证以及授权-->
    /page/toLogin=anon
    /css/**=anon
    /js/**=anon
    <!-- /page/toAdmin = roles["2"] -->
    <!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
    </value>
    </property>
    </bean>
    
    </beans>

需要自己修改的就从自定义Reaml开始

<bean id="myRealm" class="com.wx.security.ShiroSecurityRealm">

然后是下面的加密方法,这里是shiro自带的MD5加密,加密次数是1024次并且加了盐(所以你在用户注册的时候也要用MD5加密对密码进行加密,并且将盐值放入数据库中,以供shiro进行加盐加密后能和数据库中加密后的密码对应起来)也就是这一句

            <!-- 加密算法 -->
            <property name="hashAlgorithmName" value="MD5"></property>
            <!-- 加密次数 -->
            <property name="hashIterations" value="1024"></property>

然后是第一个是com.wx.security.ShiroSecurityRealm 你自己写的一个ShiroSecurityRealm类继承了shiro 的AuthorizingRealm类,类的具体写法如下:

public class ShiroSecurityRealm extends AuthorizingRealm {
    @Autowired
    private SysUserService sysUserService;
    /*
     * @Autowired private SysUserMapper sysUserMapper;
     *///注意这里只能注入接口,因为shiro的是比springmvc先加载的所以如果直接注入类的话就会有找不到依赖的错误,因为执行到这的时候还没有bean还没有生成

    @SuppressWarnings("unused")
    @Override
    //权限管理
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        
        String username = principals.toString();
        int userId = sysUserService.findUser(username).getUserid();
        SysUser user = sysUserService.findUserById(userId);
        if(user!=null) {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            for(SysRole role:sysUserService.findRole(userId)){
                info.addRole(role.getRole_key());//将角色的编码放入role中,如果需要别的可以再换
                for(SysAuthority permission:sysUserService.findPremission(role.getRole_key())) {
                    info.addStringPermission(permission.getData_url());//将权限编码放入info中,如果需要其他的可以再get
                }
                
            }
            return info;
        }else {
        return null;
        }
    }

    @SuppressWarnings("unused")
    @Override
    //登陆管理
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        // TODO Auto-generated method stub
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;//这个token是controller层传入的token
        /*
         * System.out.println(token.getUsername());
         * System.out.println(token.getPassword());
         */
        SysUser user = sysUserService.findUser(token.getUsername());//取出controller中传入token中保存的用户名,并查出来一条用户信息
        ByteSource salt = ByteSource.Util.bytes(user.getSalt());//得到该用户的密码盐值
        if(user != null) {
            return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),salt,this.getName());//SimpleAuthenticationInfo是用于验证前台传入得用户名密码是否匹配的,包含四个参数,具体参数的作用可百度
        }
        return null;
    }
    


    

}

 

首先要注意我注释的地方,这个类需要service的方法去查询出用户的权限和角色给shiro管理,所以需要注入service类,但是应该是和加载顺序有关系,在执行shiro这个自定义的realm时候service类还没有变成注入到工厂中,所以无法注入类,所以要注入对应的接口

然后,想要理解重写的这两个方法需要知道一个完成的流程,从用户登陆开始,下面是代码:

 

    @RequestMapping("/login")
    @ResponseBody 
    public void checkLogin(String username, String password) throws IOException {
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        Subject currentUser = SecurityUtils.getSubject();
        if(!currentUser.isAuthenticated()) {
            try {
            //使用shiro来进行验证
            currentUser.login(token);
            }
            /* result.put("sucess", true); */
            catch (AuthenticationException e) {
                result.setSuccess(false);
                result.setMessage("登录失败");
                super.writeJSON(result);
                return;
                }
        } 
        String name = (String)SecurityUtils.getSubject().getPrincipal();//去得到SimpleAuthenticationInfo的第一个参数,我们这里就是用户名
        SysUser user = sysUserService.findUser(name);
        if(user.getFlat()==0) {
            result.setSuccess(false);
            result.setMessage("员工已离职");
            super.writeJSON(result);
            return;
        }
        result.setSuccess(true);
        result.setMessage("登录成功");
        super.writeJSON(result);
        return;
        
    }

 

在执行到 currentUser.login(token);这一句的时候会进入shiro进行用户验证,也就是进入自定义的realm的doGetAuthenticationInfo方法中,在执行到SimpleAuthenticationInfo是真正开始验证,里面包含了四个参数,具体含义可以百度,大概就是第一个使用户,第二个是密码,第三个是密码加密的盐值,第四个是本类的名字,验证成功后shiro是把参数放入session中,登陆成功后会进入到权限管理的方法中也就是上面自定义reaml的doGetAuthorizationInfo中这个方法就是根据你上面登陆的用户名查询出来用户对应的角色和对应的权限,将权限和角色交由shiro管理。然后就是如何使用shiro进行权限管理了,shiro管理的方法很简单,由上面可知在用户登陆的时候shiro就已经得到该用户的所有权限和角色,然后就是你在需要权限管理的地方进行写上对应权限字段shiro就会自动把登陆时注入的权限跟你写在对应地方的权限字符进行比较,字符相同的就是拥有权限,不一样的就是没有权限,会返回401?(忘了),具体设置权限是有三种方法的,这里简单说一下:

1.在jsp页面可以使用标签实现按钮级别的权限管理

2.在方法上(controller或者service)加入注解,实现方法级别的权限管理

3.例如上面的spring-shiro.xml中对路劲进行配置,也可以实现方法级别的权限管理

暂时就这么多,自己试一遍就懂了,最后的shiro使用不懂可以百度,shiro实现权限管路的三种方法,百度到处都是

 

posted on 2019-04-25 14:44  沈大侠  阅读(185)  评论(0编辑  收藏  举报