ssm+shiro框架搭建笔记(6)

7 篇文章 0 订阅

配置shiro

(1). 使用maven导入依赖包。

   <!-- shiro start -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-quartz</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-core</artifactId>
        <version>2.6.6</version>
    </dependency>
    <!-- shiro end -->

(2). 配置web.xml。

文件添加一下配置信息:
配置拦截器,拦截路径为/*

<!-- shiro 安全过滤器滤器  start-->
<!-- The filter-name matches name of a 'shiroFilter' bean inside applicationContext.xml -->
<!-- 这个拦截器的filter-name:shiroFilter 要在spring配置文件中有配置-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <async-supported>true</async-supported>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<!-- Make sure any request you want accessible to Shiro is filtered. /* catches all -->
<!-- requests.  Usually this filter mapping is defined first (before all others) to -->
<!-- ensure that Shiro works in subsequent filters in the filter chain:             -->
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/</url-pattern>
</filter-mapping>
<!-- shiro 安全过滤器滤器  end-->

(3).配置spring.xml文件。

文件添加一下配置信息:

<!-- shiro配置 -->
<import resource="spring-shiro.xml"/>

(4).配置spring-mvc.xml文件。

文件添加一下配置信息:

<!-- 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions) start,需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证   -->
<bean
    class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
    depends-on="lifecycleBeanPostProcessor">
    <property name="proxyTargetClass" value="true" />
</bean>
<!-- 开启Shiro的注解end -->

(5).配置spring-shiro.xml文件。

文件配置信息:<br />

<!--   
   Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行  
   Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持   
-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <!-- Shiro的核心安全接口,这个属性是必须的 --> 
    <property name="securityManager" ref="securityManager"/>
    <!-- 要求登录时的链接(登录页面地址),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 --> 
    <property name="loginUrl" value="/login.html"/>
    <!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码) -->  
    <!-- <property name="successUrl" value="/" ></property> -->  
    <!-- 用户访问未对其授权的资源时,所显示的连接 -->  
    <property name="unauthorizedUrl" value="/"></property>  
    <property name="filterChainDefinitions">
        <value>
            /login.html = anon
        </value>
    </property>
    <!-- 自定义拦截器 -->
    <!-- <property name="filters">
        <util:map>
            <entry key="authc" value-ref="formAuthenticationFilter"/>
        </util:map>
    </property> -->
</bean>


<!-- 缓存管理器 使用本地Ehcache实现 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
</bean>
<!-- 凭证匹配器 -->
  <!--   <bean id="credentialsMatcher" class="com.github.zhangkaitao.shiro.chapter12.credentials.RetryLimitHashedCredentialsMatcher">
    <constructor-arg ref="cacheManager"/>
    <property name="hashAlgorithmName" value="md5"/>
    <property name="hashIterations" value="2"/>
    <property name="storedCredentialsHexEncoded" value="true"/>
</bean> -->    
    <!-- 会话ID生成器 -->
     <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
<!-- 会话Cookie模板 -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <constructor-arg value="jsid"/>
    <!-- 设置Cookie名字,默认为JSESSIONID -->
    <!-- <property name="name" value="" /> -->
    <!-- 设置Cookie的域名,默认空,即当前访问的域名 -->
    <!-- <property name="domain" value="" /> -->
    <!-- 设置Cookie的路径,默认空,即存储在域名根下 -->
    <!-- <property name="path" value="" /> -->
    <!-- 如果设置为true,则客户端不会暴露给客户端脚本代码,使用HttpOnly cookie有助于减少某些类型的跨站点脚本攻击;  此特性需要实现了Servlet 2.5 MR6及以上版本的规范的Servlet容器支持 -->
    <property name="httpOnly" value="true"/>
    <!-- 设置Cookie的过期时间,秒为单位,默认-1表示关闭浏览器时过期Cookie -->
    <property name="maxAge" value="-1"/>
</bean>
<!-- 会话DAO -->
  <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
  <!--   <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/> -->
  <!-- 会话ID生成器  -->
    <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
</bean>
<!-- 会话验证调度器 -->
   <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
    <!-- 设置调度时间间隔,单位毫秒,默认就是1小时 -->
    <!-- <property name="interval" value=""/> -->
    <property name="sessionValidationInterval" value="1800000"/>
    <property name="sessionManager" ref="sessionManager"/>
</bean>
<!-- 会话管理器 -->
   <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <!-- 设置全局会话超时时间,默认30分钟,即如果30分钟内没有访问会话将过期-->
    <property name="globalSessionTimeout" value="1800000"/>
    <!-- session失效后是否删除 -->
    <!-- 默认是开启的,在会话过期后会调用SessionDAO的delete方法删除会话:如会话时持久化存储的,可以调用此方法进行删除 -->
    <property name="deleteInvalidSessions" value="true"/>
    <!-- 是否开启会话验证器,默认是开启的 -->
    <property name="sessionValidationSchedulerEnabled" value="true"/>
    <!-- 设置会话验证调度器,默认就是使用 -->
    <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>        
    <property name="sessionDAO" ref="sessionDAO"/>
    <!-- 是否启用/禁用Session Id Cookie,默认是启用的;如果禁用后将不会设置Session Id Cookie, 即默认使用了Servlet容器的JSESSIONID,且通过URL重写(URL中的“;JSESSIONID=id”部分)保存Session Id -->
    <property name="sessionIdCookieEnabled" value="true"/>
    <!-- 会话Cookie模板 -->
 <!--    <property name="sessionIdCookie" ref="sessionIdCookie"/> -->
</bean>
<!-- 自定义Realm实现 -->
<bean id="shiroRealm" class="com.lcl.shiro.filter.realmManage"/>    
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="shiroRealm"/>
    <property name="sessionManager" ref="sessionManager"/>
    <!-- <property name="cacheManager" ref="cacheManager"/> -->
</bean>
<!-- Shiro生命周期处理器-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
    <property name="arguments" ref="securityManager"/>
</bean> 
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager" />
</bean>

(6).配置ehcache-shiro.xml,为以后使用做准备。

文件配置信息:

<?xml version="1.0" encoding="UTF-8"?>  
<ehcache updateCheck="false" name="shiroCache">  
<diskStore path="java.io.tmpdir" />  

<defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="18000"
        timeToLiveSeconds="18000"
        overflowToDisk="false"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"  
    />   
</ehcache> 

(7).测试代码。

realmManage.java—登录校验类,在之前项目中 创建
package com.lcl.shiro.filter;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.lcl.sys.service.LoginService;
public class realmManage extends AuthorizingRealm implements Serializable{
/**
* Logger日志
*/
private static final Logger LOGGER = LoggerFactory.getLogger(realmManage.class);
@Autowired
private LoginService loginService;
/**
* 权限授权函数,查詢用戶的所擁有的權限
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
String userName = (String) principal.getPrimaryPrincipal();
// 取得用户的所有权限
Set permissions = new HashSet();
Set roleNames = new HashSet();
//查詢用戶角色集合
List roleList = loginService.selectRolesByName(userName);
for(String role : roleList){
roleNames.add(role);
}
//查詢用戶權限集合
List permissionList = loginService.selectHasPermissionsByName(userName);
for(String permissionUnion : permissionList){
permissions.add(permissionUnion);
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
info.setStringPermissions(permissions);
return info;
}
/**
* 身份认证函数
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authctoken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authctoken;
String userName = (String) token.getPrincipal(); // 得到用户名
String pwd = new String((char[]) token.getCredentials()); // 得到密码
String password =”“;
try {
password = loginService.selectPwdByName(userName);
} catch (Exception e) {
throw new ShiroException();//账号异常
}
if (password == null || “”.equals(password)) {
throw new UnknownAccountException(); //如果用户名错误
}
if(!pwd.equals(password)) {
throw new IncorrectCredentialsException(); //如果密码错误
}
//如果身份认证验证成功,返回一个AuthenticationInfo实现;
return new SimpleAuthenticationInfo(userName, pwd, getName());
}
}

LoginController.java—Controller类 在登录控制类 添加一下方法

@RequestMapping(value="login")
@ResponseBody
public Map<String, Object> login(@RequestParam("userName") String username, @RequestParam("pwd") String pwd,@RequestParam("autoLogin") String autoLogin,    @RequestParam("remember") String remember){
    Map<String, Object> oMap = new HashMap<String, Object>();
    Map<String, Object> errorInfo = new HashMap<String, Object>();      
    //得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证) 
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(username, pwd);
    try {
        //登录,即身份验证  
        if (!subject.isAuthenticated()) {//判断时候已经登录
            subject.login(token);
        }
        //处理登录后信息保存
        UserInfo userinfo = loginService.selectUserInfoByName(username);
        Session session = subject.getSession();
        session.setAttribute(SessionConstant.LOGIN_USER_INFO, userinfo);
        LOGGER.info("账号密码登录验证------------------------success");
        oMap.put("success", "success");
    } catch (UnknownAccountException e) {
        LOGGER.info("------------------账号不存在--------------");
        errorInfo.put("userName", "账号不存在");
        oMap.put("errorInfo", errorInfo);
        oMap.put("success", "error");
        return oMap;
    } catch (IncorrectCredentialsException e) {
        LOGGER.info("------------------密码错误--------------");
        errorInfo.put("pwd", "密码错误");
        oMap.put("errorInfo", errorInfo);
        oMap.put("success", "error");
        return oMap;
    } catch (ShiroException e) {
        LOGGER.info("------------------账号密码错误--------------");
        errorInfo.put("pwd", "密码错误");
        errorInfo.put("userName", "账号错误");
        oMap.put("errorInfo", errorInfo);
        oMap.put("success", "error");
        return oMap;
    }
    return oMap;
}

LoginService.java—Service接口 添加一下方法

 /**
 * 
* @Title: selectPwdByName 
* @Description: 根据用户账号查询密码 
* @param username
* @return String 返回类型 
* @throws
 */
String selectPwdByName(String username);
/**
 * 
* @Title: selectRolesByName 
* @Description: 根据用户账号查询角色集合
* @param username
* @return List<String> 返回类型 
* @throws
 */
List<String> selectRolesByName(String userName);
/**
 * 
* @Title: selectPermissionsByName 
* @Description: 根据用户账号查询用戶權限集合标识
* @param @param userName
* @return List<String> 返回类型 
* @throws
 */
List<String> selectHasPermissionsByName(String userName);
/**
 * 
* @Title: selectUserInfoByName 
* @Description: 根据用户名查询用户信息 
* @param @param username
* @return UserInfo    返回类型 
* @throws
 */
UserInfo selectUserInfoByName(String username);

LoginServiceImp—Service接口实现类 实现以下方法

@Override
public String selectPwdByName(String userName) {
return sysManageMapper.selectPwdByName(userName);
}
@Override
public List selectRolesByName(String userName) {
return sysManageMapper.selectRolesByName(userName);
}
@Override
public List selectHasPermissionsByName(String userName) {
return sysManageMapper.selectHasPermissionsByName(userName);
}
@Override
public UserInfo selectUserInfoByName(String username) {
return sysManageMapper.selectUserInfoByName(username);
}

TestMapper.java—dao接口 添加以下DAO接口

  /**
 * 
* @Title: selectPwdByName 
* @Description: 根据用户查询密码 
* @param username
* @return String    返回类型 
* @throws
 */
String selectPwdByName(String username);
/**
 * 
* @Title: selectRolesByName 
* @Description: 根据用户账号查询角色集合
* @param username
* @return List<String> 返回类型 
* @throws
 */
List<String> selectRolesByName(String userName);
/**
 * 
* @Title: selectPermissionsByName 
* @Description: 根据用户账号查询用戶權限集合标识
* @param @param userName
* @return List<String> 返回类型 
* @throws
 */
List<String> selectHasPermissionsByName(String userName);
/**
 * 
* @Title: selectUserInfoByName 
* @Description: 根据用户名查询用户
* @param @param username
* @return UserInfo    返回类型 
* @throws
 */
UserInfo selectUserInfoByName(String username);

—–实体类 只写名字。可以对照mapper.xml自己创建

—UserInfo.java
—PermissionInfo.java
—RoleInfo.java

sysManageMapper.xml—sql配置文件

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.lcl.sys.dao.SysManageMapper" >
<!-- 用户信息关联表 -->
<resultMap id="UserInfoBaseResultMap" type="com.lcl.sys.model.UserInfo" >
<id column="id" property="id" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="pwd" property="pwd" jdbcType="VARCHAR" />
<result column="real_name" property="realName" jdbcType="VARCHAR" />
<result column="is_delete" property="isDelete" jdbcType="CHAR" />
<result column="creater" property="creater" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="DATE" />
<result column="updater" property="updater" jdbcType="VARCHAR" />
<result column="update_time" property="updateTime" jdbcType="DATE" />
  </resultMap>
  <!-- 权限信息关联表 -->
  <resultMap id="PermissionInfoBaseResultMap" type="com.lcl.sys.model.PermissionInfo" >
<id column="Id" property="id" jdbcType="VARCHAR" />
<result column="pid" property="pid" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="url" property="url" jdbcType="VARCHAR" />
<result column="unique_name" property="unique" jdbcType="VARCHAR" />
<result column="type" property="type" jdbcType="CHAR" />
<result column="icon" property="icon" jdbcType="VARCHAR" />
<result column="is_visiable" property="isVisiable" jdbcType="CHAR" />
<result column="sort_num" property="sortNum" jdbcType="INTEGER" />
<result column="creater" property="creater" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="DATE" />
<result column="updater" property="updater" jdbcType="VARCHAR" />
<result column="update_time" property="updateTime" jdbcType="DATE" />
<result column="isParent" property="isParent" jdbcType="BIT" />
  </resultMap>
  <!-- 角色信息关联表 -->
   <resultMap id="RoleInfoBaseResultMap" type="com.lcl.sys.model.RoleInfo" >
<id column="Id" property="id" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="remark" property="remark" jdbcType="VARCHAR" />
<result column="creater" property="creater" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="DATE" />
<result column="updater" property="updater" jdbcType="VARCHAR" />
<result column="update_time" property="updateTime" jdbcType="DATE" />
  </resultMap>
  <!-- 根据用户查询密码  -->
  <select id="selectPwdByName" resultType="string" parameterType="string">
SELECT pwd FROM tb_user tu WHERE tu.name=#{username} AND tu.is_delete='0'
  </select>
  <!-- 根据用户账号查询角色集合 -->
  <select id="selectRolesByName" resultType="string" parameterType="string">
   SELECT
tr.name
FROM
    tb_role tr
WHERE
    tr.id IN (
        SELECT
            tur.role_id
        FROM
            tb_user_role tur
        WHERE
            tur.id = (
                SELECT
                    id
                FROM
                    TB_USER TU
                WHERE
                    TU. NAME = #{username} AND tu.is_delete='0'
            )
    )
      </select>
  <!-- 根据用户账号查询用戶權限集合标识 -->
  <select id="selectHasPermissionsByName" resultType="string" parameterType="string">
  SELECT
tp.unique_name
FROM
    tb_permission tp
WHERE
    tp.Id IN (
        SELECT
            trp.permission_id
        FROM
            tb_role_permission trp
        WHERE
            trp.role_id IN (
                SELECT
                    tr.id
                FROM
                    tb_role tr
                WHERE
                    tr.id IN (
                        SELECT
                            tur.role_id
                        FROM
                            tb_user_role tur
                        WHERE
                            tur.id = (
                                SELECT
                                    id
                                FROM
                                    TB_USER TU
                                WHERE
                                    TU. NAME = 'admin'
                            )
                    )
            )
    )
  </select>
 <!--  根据用户名查询用户 -->
  <select id="selectUserInfoByName" parameterType="string" resultMap="UserInfoBaseResultMap">
    select tu.* from tb_user tu where tu.name = #{username}
  </select>
</mapper>     

至此,一个简单的整合完成,已经有简单的登录验证,后面会陆续加上缓存,filter。

此时项目的目录结构如下:

java文件:
--com.lcl
    --base                  基类包 用于存放顶层父类实现通用方法。
    --constant              存放常量
    --filter                放置项目filter
    --shiro.filter          存放shiro有关的filter以及Realm。
    --sys                   业务类模块包
        --controller        控制层
        --dao               dao层
        --mapping           mapper文件
        --model             实体类
        --service           service接口
            --imp           service实现类
    --util                  工具类
    --validator             校验接口存放
资源文件:
--validation                校验配置文件存放  
   sysValidationMessages.properties         按模块存放                               
config.properties           数据源配置文件          
ehcache-shiro.xml           缓存配置文件
log4j.properties            log4j配置文件
mybatis-interceptor.xml     mybatis分页配置
spring-mvc.xml              springMVC配置文件    
spring-mybatis.xml          mybatis配置文件
spring-service-tx.xml       事物配置文件
spring-shiro.xml            shiro配置文件
spring.xml                  spring配置文件
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值