SSM集成Shiro

SSM集成Shiro

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。 —— [ 百度百科 ]

第一次写博客,很多地方可能语句不通,只是作为项目当中的一些记录.开发工具使用的Eclipse.项目刚开始代码还在逐步完善中,请多多指教.jsp使用了JQuery,Easyui前段框架[Github][2].

贴上pom:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.jxj</groupId>
  <artifactId>ssm-shiro-0624-jxj</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>ssm-shiro-0624-jxj Maven Webapp</name>
  <url>http://maven.apache.org</url>
   <!-- 统一版本号 -->
  <properties>  
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
        <!-- spring版本号 -->  
        <spring.version>3.2.4.RELEASE</spring.version>  
        <!-- mybatis版本号 -->  
        <mybatis.version>3.2.4</mybatis.version>  
        <!-- log4j日志文件管理包版本 -->  
        <slf4j.version>1.6.6</slf4j.version>  
        <log4j.version>1.2.9</log4j.version>
        <shiro.version>1.3.2</shiro.version>  
   </properties>

  <dependencies>
       <dependency>  
            <groupId>javax.servlet</groupId>  
            <artifactId>servlet-api</artifactId>  
            <version>2.5</version>  
            <!-- scope=compile 的情况(默认compile),也就是说这个项目在编译、测试,运行阶段都需要这个artifact对应的jar包在classpath中 -->  
            <!-- scope=provided ,则可以认为这个provided是目标容器已经provided这个artifact,它只影响到编译、测试阶段,运行阶段,假定目标容器已经提供了这个jar包 -->  
            <scope>provided</scope>  
        </dependency> 
        <!-- spring 核心包 -->  
        <!-- springframe start -->  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-core</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-web</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-oxm</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-tx</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-jdbc</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-webmvc</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-aop</artifactId>  
            <version>${spring.version}</version>  
        </dependency>

        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-test</artifactId>  
            <version>${spring.version}</version>  
        </dependency>

        <!-- mybatis核心包 -->  
        <dependency>  
            <groupId>org.mybatis</groupId>  
            <artifactId>mybatis</artifactId>  
            <version>${mybatis.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.mybatis.generator</groupId>  
            <artifactId>mybatis-generator-core</artifactId>  
            <version>1.3.2</version>  
        </dependency>  

        <!-- mybatis/spring包 -->  
        <dependency>  
            <groupId>org.mybatis</groupId>  
            <artifactId>mybatis-spring</artifactId>  
            <version>1.2.2</version>  
        </dependency> 
         <!-- MySql -->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.32</version>
        </dependency> 
        <!-- 数据源包 -->  
        <dependency>  
            <groupId>com.alibaba</groupId>  
            <artifactId>druid</artifactId>  
            <version>1.0.2</version>  
        </dependency> 
        <!-- json数据 -->  
        <dependency>  
            <groupId>org.codehaus.jackson</groupId>  
            <artifactId>jackson-mapper-asl</artifactId>  
            <version>1.9.13</version>  
        </dependency> 
       <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.8.3</version>
        </dependency>
       <!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.2</version>
        </dependency>
       <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
       <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
       <!-- https://mvnrepository.com/artifact/net.sf.ezmorph/ezmorph -->
        <dependency>
            <groupId>net.sf.ezmorph</groupId>
            <artifactId>ezmorph</artifactId>
            <version>1.0.6</version>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.3</version>
            <classifier>jdk15</classifier>
        </dependency> 




         <!-- 日志文件管理包 -->  
        <dependency>  
            <groupId>log4j</groupId>  
            <artifactId>log4j</artifactId>  
            <version>${log4j.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.slf4j</groupId>  
            <artifactId>slf4j-api</artifactId>  
            <version>${slf4j.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.slf4j</groupId>  
            <artifactId>slf4j-log4j12</artifactId>  
            <version>${slf4j.version}</version>  
        </dependency> 

        <!-- 格式化对象,方便输出日志 -->  
        <dependency>  
            <groupId>com.alibaba</groupId>  
            <artifactId>fastjson</artifactId>  
            <version>1.1.41</version>  
        </dependency>  
        <dependency>  
            <groupId>org.apache.tomcat</groupId>  
            <artifactId>jsp-api</artifactId>  
            <version>6.0.32</version>  
            <scope>provided</scope>  
        </dependency> 
        <!-- 映入JSON -->  
        <dependency>  
            <groupId>org.codehaus.jackson</groupId>  
            <artifactId>jackson-mapper-asl</artifactId>  
            <version>1.9.13</version>  
        </dependency>
        <!-- 上传组件包 -->  
        <dependency>  
            <groupId>commons-fileupload</groupId>  
            <artifactId>commons-fileupload</artifactId>  
            <version>1.3.1</version>  
        </dependency>  

        <dependency>  
            <groupId>commons-io</groupId>  
            <artifactId>commons-io</artifactId>  
            <version>2.4</version>  
        </dependency>  

        <dependency>  
            <groupId>commons-codec</groupId>  
            <artifactId>commons-codec</artifactId>  
            <version>1.9</version>  
        </dependency>  
        <!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 -->  
        <dependency>  
            <groupId>commons-dbcp</groupId>  
            <artifactId>commons-dbcp</artifactId>  
            <version>1.2.2</version>  
        </dependency>  
        <dependency>  
            <groupId>junit</groupId>  
            <artifactId>junit</artifactId>  
            <version>4.8</version>  
            <scope>test</scope>  
        </dependency>  
        <!--jsp标签 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!--Shiro-->
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-core</artifactId>
          <version>${shiro.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-web</artifactId>
          <version>${shiro.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-spring</artifactId>
          <version>${shiro.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-ehcache</artifactId>
          <version>${shiro.version}</version>
        </dependency>                 
</dependencies>
  <!-- 定制打包后的包名 -->  
  <build>
    <finalName>0619-jxj</finalName>
  </build>
</project>

一.先建立一个maven工程,集成Spring和MyBatis(略过)
二.使用MyBatis的代码生成dao及对应的xml和实体类
生成过程:(放在其他文件夹中)
1.新建一个文件夹jxj(名字,位置自定)
2.将mybatis-3.4.1 和mybatis-generator-core-1.3.5 和mysql-connector-java-5.1.38 的jar包放到文件夹中
3.再新建一个xml文件.代码

<?xml version="1.0" encoding="UTF-8"?>    
<!DOCTYPE generatorConfiguration    
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"    
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">    
<generatorConfiguration>    
<!-- 数据库驱动-->    
    <classPathEntry  location="mysql-connector-java-5.1.38.jar"/> 
    <context id="DB2Tables"  targetRuntime="MyBatis3">    
        <commentGenerator>    
            <property name="suppressDate" value="true"/>    
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->    
            <property name="suppressAllComments" value="true"/>    
        </commentGenerator>    
        <!--数据库链接URL,用户名、密码 -->    
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/zjtblog" userId="root" password="123456">    
        </jdbcConnection>    
        <javaTypeResolver>    
            <property name="forceBigDecimals" value="false"/>    
        </javaTypeResolver>    
        <!-- 生成模型的包名和位置-->    
        <javaModelGenerator targetPackage="test.domain" targetProject="src">    
            <property name="enableSubPackages" value="true"/>    
            <property name="trimStrings" value="true"/>    
        </javaModelGenerator>    
        <!-- 生成映射文件的包名和位置-->    
        <sqlMapGenerator targetPackage="test.mapping" targetProject="src">    
            <property name="enableSubPackages" value="true"/>    
        </sqlMapGenerator>    
        <!-- 生成DAO的包名和位置-->    
        <javaClientGenerator type="XMLMAPPER" targetPackage="test.Dao" targetProject="src">    
            <property name="enableSubPackages" value="true"/>    
        </javaClientGenerator>    
        <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->    
        <table tableName="t_role_menu" domainObjectName="Tuser" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>  
    </context>    
</generatorConfiguration>   

4.再新建一个文件夹用户存放生成的代码
6.打开cmd定位到这个文件夹,执行:

java -jar mybatis-generator-core-1.3.5.jar -configfile generatorConfig.xml -overwrite

注:由于不是在项目中生成代码,所以xml文件里面的路径要同项目里的路径要一样,这样生成后可以直接复制进去

三 集成shiro
1. spring-mvc.xml
2. spring-mybatis.xml
3. spring-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util"  
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-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/context  
    http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc  
    http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/util   
    http://www.springframework.org/schema/util/spring-util.xsd">       

    <!-- 自定义Realm -->
    <bean id="userRealm" class="com.jxj.shiro.UserRealm">  

    </bean> 

     <!-- 安全管理器 -->  
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
        <property name="realm" ref="userRealm" />
        <!-- 注入缓存管理器   
        <property name="cacheManager" ref="cacheManager"/>  --> 
         <!-- 注入session管理器 -->
        <property name="sessionManager" ref="sessionManager" /> 
        <!-- 记住我  
        <property name="rememberMeManager" ref="rememberMeManager"/>  --> 
    </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>

     <!-- 启用shrio授权注解拦截方式 -->  
    <!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->  
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
        <!-- 调用我们配置的权限管理器 -->  
        <property name="securityManager" ref="securityManager" />  
        <!-- 配置我们的登录请求地址 -->  
        <property name="loginUrl" value="/user/login" />  
        <!-- 配置我们在登录页登录成功后的跳转地址,因为登录成功后的处理逻辑在LoginController里硬编码为main.jsp了) -->   
        <!--<property name="successUrl" value="/jsp/index" />   -->
        <!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->  
        <property name="unauthorizedUrl" value="/user/hello" />  

        <!-- 权限配置 -->  
        <property name="filterChainDefinitions">  
            <value>  
                <!-- anon表示此地址不需要任何权限即可访问 -->  
                /user/login=anon  
                /icon/**=anon  
                /js/**=anon 
                /css/**=anon 
                /images/**=anon
                /user/logout=logout
                /user/hello=anon  
                <!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login -->  
                /** = authc  
            </value>  
        </property>  
    </bean>    
    <!-- 开启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>     
    <!-- Shiro生命周期处理器-->  
    <bean id="lifecycleBeanPostProcessor"   class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  

    <!-- <bean id="accountService" class="com.jxj.service.impl.UserServiceImpl">
        <property name="userService" ref="userService"></property>
    </bean>  -->
</beans>

4.自定义的 UserRealm
4.1 UserRealm 集成 AuthorizingRealm 有两个方法:
doGetAuthorizationInfo 授权
doGetAuthenticationInfo 验证
验证就是将账号和密码交给 SimpleAuthenticationInfo 来验证

System.out.println("登陆验证....");
        String username = (String) token.getPrincipal();//传进来的账号
        User user = userService.findByUsername(username);//根据账号从数据库查询用户信息
        if(user == null) {
            System.out.println("======不存在该用户=========>");
            throw new UnknownAccountException("不存在该用户");//没找到帐号 

        }
         System.out.println("数据库的账号:"+user.getUserName()+" 密码:"+user.getPassword());
        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( 
            user.getUserName(), //用户名  
            user.getPassword(), //密码 
            getName()
                );
        return authenticationInfo;

授权这里我花了一些时间,所以多写点:
第一步 获取当前用户

String username = (String)pc.getPrimaryPrincipal(); 

判断用户不为空后,从数据库获取用户对应对的角色将其放进去

//获取用户角色
            List<String> roles = getRoleList(username);   
            authorizationInfo.addRoles(roles);
/**
     * 根据用户 获取部门集
     * @param username
     * @return
     */
    private List<String> getRoleList(String username){
        List<String> role = new ArrayList<String>();
        List<Role> roles = userService.getRoleByUsername(username);
        for(Role r : roles) {
            String str = username+":"+r.getName();
            role.add(str);
        };
        return role;
    }

根据用户获取角色集后,以 用户名:角色名 的集合,
在控制器中就可以获取是否有这个角色的权限

我的项目是 以资源和资源对应的按钮权限
这里写图片描述
首先从数据库获取资源 名称和对应的增删改查等权限分别放入集合,然后再嫁给shiro

/**
     * 获取 用户对应的资源权限
     * @param username
     * @return
     */
    private List<String> getPermissionList(String username){
        List<String> permission = new ArrayList<String>();
        List<RoleMenu> menulist =menuService.selectRoleMenuByUserName(username);
        for(RoleMenu rm : menulist) {
            String menuName = menuService.menuById(rm.getMenuId()).getName(); //菜单名称
            //String roleName = roleService.getRoleByRoleId(rm.getRoleId()).getName(); //部门名字
            if(rm.getAddTx().equals("checked")) {               
                permission.add(menuName+":add");
            };
            if(rm.getDelTx().equals("checked")) {
                permission.add(menuName+":del");
            };
            if(rm.getEditTx().equals("checked")) {
                permission.add(menuName+":edit");
            };
            if(rm.getSeeTx().equals("checked")) {
                permission.add(menuName+":see");
            };
            permission.add(menuName+":power:"+rm.getPowertx());
        };
        return permission;
    }

授权:

/**
     * 获取权限信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
        System.out.println("UserRealm当前用户授权");
        String username = (String)pc.getPrimaryPrincipal();     
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); 
        if (username!=null) {
            //获取用户角色
            List<String> roles = getRoleList(username);   
            authorizationInfo.addRoles(roles);
            //资源集按钮
            List<String> mlist=getPermissionList(username);
            authorizationInfo.addStringPermissions(mlist);      

        }else {
            System.out.println("UserRealm当前用户没有获取到用户");
        }
        return authorizationInfo;
    }

到这里就完成了授权:
在控制器中就可以查看是否有某个权限了,我要修改用户资料:

   /**
     * 编辑用户
     * @param str 接收的用户id
     * @param request
     * @return 页面地址
     */
    @RequestMapping("/edit")
    public String editUserInfo( Integer uid,HttpServletRequest request) {
        System.out.println("-----------------开始修改用户资料"+uid);
        Subject subject = SecurityUtils.getSubject();  
        boolean isPermitted =subject.isPermitted("用户管理:edit");
        User user = userService.selectUser(uid);
        if(isPermitted) {
            List<Map> roleNames = getRoleName();
            request.setAttribute("roleNames",roleNames);
            request.setAttribute("user",user);
            request.setAttribute("message","edit");
            return "user/user-detail";
        }else {
           request.setAttribute("message","修改用户管理");//
           return "Exception/jurisdictionException";
        }       
    };

这样基本完成了登录及授权的工作的
这里没有加入缓存,所以每次都会查询数据库来获取相关信息

展示层: 用的Jquery和Easyui的框架,并没有用到其他的框架.因为时间的关系,除了用到的功能外,其他的都没有处理,所以页面有些不协调也有些简陋.
因为每个元素都是自己加上去的所以自由性大写,可以自己发挥
贴几张图片(确实有点丑)
这里写图片描述

这里写图片描述

这里写图片描述

浏览器兼容

  1. 目前,本编辑器对Chrome浏览器支持最为完整。建议大家使用较新版本的Chrome。
  2. IE9以下不支持
  3. IE9,10,11存在以下问题
    1. 不支持离线功能
    2. IE9不支持文件导入导出
    3. IE10不支持拖拽文件导入

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值