shiro在SSM以及与Springboot+Mybatis中的实践

公司项目使用的是前后端分离的方式编写项目,并且我们后台项目打包是打包成jar,所以没有web.xml这个文件。
公司是使用SpringBoot+Mybatis+Shiro的框架编写,使用Maven这个插件构建项目的。
下面是我根据公司项目总结的如何使用java文件来配置Shiro环境的。
参考文档如下:
     SSM中shiro的实现:
            http://blog.csdn.net/xiangwanpeng/article/details/54793768
      多Realm的学习:   
            http://blog.csdn.net/u010837612/article/details/46053249  
1、在POM.xml中加入依赖
 1.1首先我们需要了解一下shiro常用jar包含义:
           核心包shiro-core
           Web相关包shiro-web
           缓存包shiro-ehcache
           与spring整合包shiro-spring
           Ehcache缓存核心包ehcache-core
           Shiro自身日志包slf4j-jdk14





1.2加入依赖


        <dependency>  
            <groupId>org.apache.shiro</groupId>  
            <artifactId>shiro-core</artifactId>  
            <version>1.4.0</version>  
        </dependency> 
        <!--这个里面就已经会有web这个jar包了-->
       <dependency>
           <groupId>org.apache.shiro</groupId>
           <artifactId>shiro-spring</artifactId>
           <version>1.4.0</version>
       </dependency>
       <dependency>
           <groupId>org.apache.shiro</groupId>
           <artifactId>shiro-ehcache</artifactId>
           <version>1.4.0</version>
       </dependency>
2、编写核心文件
首先我们需要了解一下Realm的含义:
    shiro要进行身份验证,就要从realm中获取相应的身份信息来进行验证,简单来说,我们可以自行定义realm,
    在realm中,从数据库获取身份信息,然后和 用户输入的身份信息进行匹配。这一切都由我们自己来定义。
多Realm是由于多个不同的身份造成的
2.1在有web.xml的情况下编写
      2.1.1在web.xml中配置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>

      2.1.2编写自己的身份认证以及搜权(这个是通过继承AuthorizingRealm实现的)
        是通过doGetAuthorizationInfo授予权限和AuthenticationToken登录身份验证两个方法实现的


@Component
public class MemberAccountRealm extends AuthorizingRealm {

    @Autowired
    private MemberAccountService memberAccountService;

    /**
     * 授权(验证权限时调用)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        // 获取登录时输入的用户名  
        MemberAccount memberAccount = (MemberAccount) principals.getPrimaryPrincipal();
        String account = memberAccount.getAccount();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 用户角色授权
        addRole(account, info);
        // 用户权限授权
        addPermisson(account, info);

        return info;
    }

    /**
     * 用户身份认证(登录时调用)
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws RuntimeException{

        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)token;

        // 获取前台用户输入的用户名和密码
        String telephone = (String) token.getPrincipal();

        // 查询用户信息
        MemberAccount memberAccount=null;
        try {
            memberAccount = this.memberAccountService.queryMemberAccount(telephone, IsDelete.IS_NOT_DELETE);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        // 获取密码并加密
        String password = ShiroUtils.passwordEncrypr(String.valueOf(usernamePasswordToken.getPassword()), String.valueOf(memberAccount.getMemberId()));

        // 重新放到token中
        usernamePasswordToken.setPassword(password.toCharArray());

        // 若存在,将此用户存放到登录认证中进行密码匹配
        return new SimpleAuthenticationInfo(memberAccount,memberAccount.getPassword(), ByteSource.Util.bytes(telephone),getName());
    }
    /**
     * 
     * 模拟授予权限
     * @param loginName
     * @param info
     */
    private void addPermisson(String loginName, SimpleAuthorizationInfo info) {

        List<String> permissonList = new ArrayList<String>();
        permissonList.add("sys:user:delete");
        permissonList.add("sys:user:update");
        permissonList.add("sys:user:save");
        permissonList.add("sys:user:list");
        //用户角色列表
        Set<String> permissonSet = new HashSet<String>();     
        for ( String perm : permissonList ) {
            if (StringUtils.isBlank(perm)) {
                continue;
            }
            permissonSet.addAll(Arrays.asList(perm.trim().split(",")));
        }
        info.setStringPermissions(permissonSet);
    }

    /**
     * 
     * 用户角色授权
     * @param loginName
     * @param info
     */
    private void addRole(String loginName, SimpleAuthorizationInfo info) {
        List<String> RoleList = new ArrayList<String>();
        RoleList.add("admin");
        //用户角色列表
        Set<String> RoleSet = new HashSet<String>();
        for ( String role : RoleList ) {
            if (StringUtils.isBlank(role)) {
                continue;
            }
            RoleSet.addAll(Arrays.asList(role.trim().split(",")));
        }

        info.setRoles(RoleSet);
    }


}

      2.1.3可以自定义一个密码验证方法


public class CredentialsMatcher extends SimpleCredentialsMatcher{

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken utoken = (UsernamePasswordToken) token;
        // 获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
        String inPassword = new String(utoken.getPassword());
        // 获得数据库中的密码
        String dbPassword = (String) info.getCredentials();
        // 进行密码的比对
        return this.equals(inPassword, dbPassword);
    }

}

      2.1.4在src目录下家里ehcache.xml,文件内容如下:


<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  -->
<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <diskStore path="./target/tmp"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element beforeQuery it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element beforeQuery it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

    <!--Predefined caches.  Add your cache configuration settings here.
        If you do not have a configuration for your cache a WARNING will be issued when the
        CacheManager starts

        The following attributes are required for defaultCache:

        name              - Sets the name of the cache. This is used to identify the cache. It must be unique.
        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element beforeQuery it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element beforeQuery it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->

    <!-- Sample cache named sampleCache1
        This cache contains a maximum in memory of 10000 elements, and will expire
        an element if it is idle for more than 5 minutes and lives for more than
        10 minutes.

        If there are more than 10000 elements it will overflow to the
        disk cache, which in this configuration will go to wherever java.io.tmp is
        defined on your system. On a standard Linux system this will be /tmp"
        -->
    <cache name="sampleCache1"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <!-- Sample cache named sampleCache2
        This cache contains 1000 elements. Elements will always be held in memory.
        They are not expired. -->
    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /> -->

    <!-- Place configuration for your caches following -->

</ehcache>

      2.1.5在spring的配置文件中加入以下代码:


     <!-- shiro start -->
    <!-- 1. 配置SecurityManager -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager" />
        <!--这个是配置的多Realm的-->
        <!--<property name="authenticator" ref="authenticator"></property>-->
        <!-- 可以配置多个Realm,其实会把realms属性赋值给ModularRealmAuthenticator的realms属性 -->
        <property name="realms">
            <list>
                <ref bean="authRealm" />
            </list>
        </property>
    </bean>

    <!-- 2. 配置CacheManager -->
    <!-- 2.1 需要加入ehcache的jar包及配置文件 -->
    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />
    </bean>

    <!-- 3. 配置Realm -->
    <!-- 3.1 直接配置继承了org.apache.shiro.realm.AuthorizingRealm的bean -->
    <bean id="authRealm" class="com.ysw.mes.common.shiro.MemberAccountRealm">
        <!-- 配置密码匹配器 -->
        <!-- 非自定义的写法
        <property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <!-- 加密算法为MD5 -->
                <property name="hashAlgorithmName" value="MD5"></property>
                <!-- 加密次数 -->
                <property name="hashIterations" value="1024"></property>
            </bean>
        </property>
         -->
         <!-- 自定义的写法 -->
         <property name="credentialsMatcher" ref="credentialsMatcher">
    </bean>
    <!-- 自定义的密码匹配器 -->
    <bean id="credentialsMatcher" class="com.ysw.mes.common.shiro.CredentialsMatcher"/>

    <!-- 4. 配置LifecycleBeanPostProcessor,可以自定义地来调用配置在Spring IOC容器中shiro bean的生命周期方法 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

    <!-- 5. 使能够在IOC容器中使用shiro的注解,但必须在配置了LifecycleBeanPostProcessor之后才可以使用 -->
    <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>

    <!-- 6. 配置ShiroFilter -->
    <!-- 6.1 id必须和web.xml中配置的DelegatingFilterProxy的<filter-name>一致。 如果不一致,会抛出NoSuchBeanDefinitionException异常,因为shiro会在IOC容器中查找名称和<filter-name> 
        值一致的filter bean -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager" />
        <property name="loginUrl" value="/login.jsp" />
        <!--<property name="successUrl" value="/home" />-->
        <!-- 配置哪些页面需要受保护,以及访问这些页面需要的权限
        <property name="filterChainDefinitions">
            <value>
                <!-- 第一次匹配优先的原则 -->
                /jsp/login.jsp* = anon
                /loginUser = anon
                /logout* = anon
                /jsp/error.jsp* = anon
                /jsp/index.jsp* = authc
                /* = authc
                /*.* = authc
            </value>
        </property>
         -->
    </bean>

    <!-- 7. 配置ModularRealmAuthenticator,可以实现多Realm认证 (公司项目并没有使用到)
    <bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
        <!-- 配置认证策略,只要有一个Realm认证成功即可,并且返回所有认证成功信息 -->
        <property name="authenticationStrategy">
            <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
        </property>
    </bean>
    -->
    <!-- shiro end -->

2.2在无web.xml的情况下编写(在这里我就不配置cache了,相信大家会写的哈)
    2.2.1编写同上的2.1.2、2.1.3
    2.2.2编写一个Shiro的配置文件如下(相当于上面的 2.1.1和2.1.5的作用)


import java.util.LinkedHashMap;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.ysw.mes.common.shiro.CredentialsMatcher;
import com.ysw.mes.common.shiro.MemberAccountRealm;

/**
 * 这个是shiro的配置文件
 * 这个文件会使用到
 *  CredentialsMatcher和MemberAccountRealm这两个文件
 * @author admin
 * 
 * 
 * 学习shiro的网址有:
 *      http://blog.csdn.net/xiangwanpeng/article/details/54793768
 * 
 *      其中对于多Realm的解释:
 * 
 *
 */
@Configuration
public class ShiroConfiguration {

    /**
     * 
     * @param manager
     * @return
     */
    @Bean(name="shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(manager);
        // 配置登录的url和登录成功的url
        bean.setLoginUrl("/toLogin");
//      bean.setSuccessUrl("/home");
        // 配置访问权限
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//        filterChainDefinitionMap.put("/jsp/login.jsp*", "anon"); //表示可以匿名访问
//        filterChainDefinitionMap.put("/loginUser", "anon"); 
//        filterChainDefinitionMap.put("/logout*","anon");
//        filterChainDefinitionMap.put("/jsp/error.jsp*","anon");
//        filterChainDefinitionMap.put("/jsp/index.jsp*","authc");
//        filterChainDefinitionMap.put("/*", "authc");//表示需要认证才可以访问
//        filterChainDefinitionMap.put("/**", "authc");//表示需要认证才可以访问
//        filterChainDefinitionMap.put("/*.*", "authc");
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return bean;
    }

    //配置核心安全事务管理器
    @Bean(name="securityManager")
    public SecurityManager securityManager(@Qualifier("authRealm") MemberAccountRealm authRealm) {
        System.err.println("--------------shiro已经加载----------------");
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(authRealm);
        return manager;
    }
    @
    /**
     * 配置自定义的权限以及身份认证器
     * 以及将自定义的密码比较器注入进去
     * @param matcher
     * @return
     */
    @Bean(name="authRealm")
    public MemberAccountRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
        MemberAccountRealm authRealm=new MemberAccountRealm();
        authRealm.setCredentialsMatcher(matcher);
        return authRealm;
    }

    /**
     * 使用的是自定义的密码比较器CredentialsMatcher
     * 
     * @return CredentialsMatcher是自定义类
     */
    @Bean(name="credentialsMatcher")
    public CredentialsMatcher credentialsMatcher() {
        return new CredentialsMatcher();
    }

    /**
     * 配置LifecycleBeanPostProcessor,可以自定义地来调用配置在Spring IOC容器中shiro bean的生命周期方法
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }
    /**
     * 使能够在IOC容器中使用shiro的注解,但必须在配置了LifecycleBeanPostProcessor之后才可以使用
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
        AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }
}

在写完上面内容后,再看一次系统后,发现登录验证的顺序原来是这样的
1、由于在shiro的配置文件中配置了
这里写图片描述
这里写图片描述
2、首先访问/toLogin这个对应的方法
这里写图片描述
3、由于subject.login(token)这个,会调用到
这里写图片描述
4、将数据塞进token和info这两个实体之后进行比较
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
课程简介:历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统后端应用权限的管理,其主要涵盖了六大核心业务模块、十几张数据库表。 其的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring BootSpring MVC、MybatisMybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值