Spring-Shiro整合

因为web项目的核心组件(Service,dao)都在spring工厂中管理,利用IOC和AOP,组建了关系松散,稳健的系统。
shiro的诸多组件也需要由spring统一管理,进而可以更好的和其他组件协作,因为shiro中大多数组件都是pojo类,更方便管理我们可以很方便地把它们从shiro.ini中迁到Spring工厂中。
pom文件

<!-- 其他依赖和web集成中 一致 ,此处省略-->
<!-- 新增一个依赖 用于在工厂中生产 ShiroFilter-->
<!-- 会传递导入shiro-core 和 shiro-web -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
</dependency>

applicationContext_shiro.xml配置文件
将shiro的三大核心组件SecurityMnager,Subject,Realm,放到配置文件,这里我们可以将shiro单独放到一个配置文件中,在Spring的配置文件中导入该配置文件即可。

    <!-- shiro配置 -->
   <!--注入自定义realm组件-->
    <bean id="myRealm" class="com.lsw.realm.MyRealm">
        <property name="userService" ref="userServiceImpl"/>
        <property name="roleService" ref="roleServiceImpl"/>
        <property name="permissionService" ref="permissionServiceImpl"/>

   <!--配置密码对比器  登陆时realm会根据盐迭代次数以及加密算法  来得出用户信息来对比数据库中的用户信息  进行身份验证-->
        <property name="credentialsMatcher">
          <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
              <!--声明迭代次数-->
              <property name="hashIterations" value="10000"/>
              <!--声明加密算法-->
              <property name="hashAlgorithmName" value="SHA-256"/>
              <!--声true=hex格式  false=base64格式明-->
              <property name="storedCredentialsHexEncoded" value="false"/>
          </bean>
        </property>
    </bean>

    <!--注入安全管理器securityManager-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--将realm注入-->
       <property name="realm" ref="myRealm"/>
        <!--将rememberMeManager注入-->
        <property name="rememberMeManager" ref="rememberMeManager"/>
        <!--注入session管理器-->
        <property name="sessionManager" ref="sessionManager"/>
    </bean>

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--注入核心组件-->
        <property name="securityManager" ref="securityManager"/>
        <!--声明未登录   没权限的-->
        <property name="loginUrl" value="/user/login"/>
        <property name="unauthorizedUrl" value="/user/error"/>
<!--过滤器链   这里后面可以用注解代替 -->
        <property name="filterChainDefinitions">
            <value>
            /user/login = anon
            /user/login = anon
            /user/all = authc,roles["admin"]
            /user/update = authc,roles["manager","seller"]
            /user/delete = authc, perms["user:update","user:delete"]
            /user/logout = logout
            </value>
        </property>
    </bean>

    <!--自定义记住我-->
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <!-- cookie的生命周期,单位:秒    7天-->
        <property name="maxAge" value="2592000"/>
        <property name="name" value="rememberMe"/>
        <!-- cookie只在http请求中可用,那么通过js脚本将无法读取到cookie信息,有效防止cookie被窃取 -->
        <property name="httpOnly" value="true"/>
    </bean>
<!--记住我管理器-->
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <property name="cookie" ref="rememberMeCookie"/>
    </bean>


    <!-- 增加session管理相关配置 -->
    <!-- 会话Cookie模板 默认可省-->
    <bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <property name="name" value="JSESSIONID04"/>
        <!-- cookie过期时间,-1:存活一个会话 ,单位:秒 ,默认为-1-->
        <property name="maxAge" value="-1"/>
        <property name="httpOnly" value="true"/>
    </bean>
<!--session管理器-->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <!-- 默认值和配置中给出的一致,所bean:sessionIdCookie 可以省略 -->
    <property name="sessionIdCookie" ref="simpleCookie"/>
    <!-- session全局超时时间, 单位:毫秒 ,30分钟 默认值为1800000   默认设置为10s-->
    <property name="globalSessionTimeout" value="10000"/>

        <!--注入session监听器-->
        <property name="sessionListeners">
            <list>
                <bean class="com.lsw.session.MySessionListener"/>
            </list>
        </property>

        <!--session检测    可以省略不写  有默认配置-->
        <!--session默认开启   但是默认时间比较长   30分钟   我们可以更改时间   来观察-->
        <property name="sessionIdUrlRewritingEnabled" value="true"/>
        <!-- 更改   检测间隔时间    15s-->
        <property name="sessionValidationInterval" value="15000"/>
    </bean>

web.xml

<!-- 会从spring工厂中获取和它同名的bean,(id="shiroFilter")
     接到请求后调用bean的doFilter方法,进行访问控制。
     因为这里本来是ShiroFilter的  我们将它放在了工厂内部  所有在web中需要定义这样一个来代替shiroFilter来拦截所有请求  然后找到工厂中预期filterName对应的ShiroFilter进行操作过滤
-->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<!-- EnvironmentLoaderListener不再需要,因为shiro环境已由spring初始化 
     springMVC,spring配置不变 -->

另外大家发现了我们在这里也直接整合了Mybatis。因为之前我们放在shiro.ini中的用户名,权限和角色信息都没有了 ,这里我们自定义了pojo类 将权限角色信息存入数据库中,在需要安全数据时候 在自定义的Realm中注入service并调用dao来进行数据库查询即可 贴一下大概结构图 和realm的代码。
大概结构:(将角色权限分别定义pojo,并将数据存在数据库,由realm中调用service,dao来查询)在这里插入图片描述
自定义realm

@Setter
public class MyRealm extends AuthorizingRealm {
    private UserService userService;//注入service  调用其中dao查询方法即可
    private  PermissionService permissionService;
    private RoleService roleService;
    @Override
    //用户做授权和权限认定
    /**
     * 当subject.login()时,shiro会调用Realm的此方法做用户信息的查询,然后做校验
     * 职责:通过用户传递来的用户名查询用户表,获得用户信息
     * 返回值:将查到的用户信息(用户名+密码)封装在AuthenticationInfo对象中返回
     * 异常:如果没有查到用户可抛出用户不存在异常;如果用户被锁定可抛出用户被锁异常;或其它自定义异常.
     * @param token
     * @return
     * @throws AuthenticationException
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取shiro中的用户名
        String username = (String) principalCollection.getPrimaryPrincipal();
        //根据用户姓名去表中查询用户角色和权限信息
        //根据用户名查询角色信息
     //   RoleService roleService = ContextLoader.getCurrentWebApplicationContext().getBean("roleServiceImpl", RoleService.class);
        Set<String> roles = roleService.queryAllRolenameByUsername(username);
        //根据用户名查权限信息
      //  PermissionService permissionService =ContextLoader.getCurrentWebApplicationContext().getBean("permissionServiceImpl", PermissionService.class);
        Set<String> permissions = permissionService.queryAllPermissionByUsername(username);
        //将用户权限和角色信息  封装到对象中
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String) authenticationToken.getPrincipal();
        //根据用户名来查询用户身份信息
       // UserService userService = (UserService)ContextLoader.getCurrentWebApplicationContext().getBean("userServiceImpl");
        //System.out.println("================"+userService);
        User user = userService.queryUserByUsername(username);
        if(user==null){
            return null;   //返回空后续会返回一个用户名不存在异常  由一场解析器处理
        }
        return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), ByteSource.Util.bytes(user.getSalt()),getName());
    }
}

至此 ,Spring集成shiro基本就完成了 后面想起来什么在做总结和大家分享 希望对大家有所帮助。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值