shiro 整合SSM

shiro 整合SSM#

一.将shiro整合到ssm中

1.在整合完ssm后,添加shiro相关jar包(shiro-all.jar)

2.在web.xml中添加shiro的配置

<!-- 配置shiroFfilter通过代理来配置,对象由spring容器来创建,但是交由servlet容器来管理 -->
<filter>
	  <filter-name>shiroFilter</filter-name>
	  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	  <init-param>
	     <!--表示bean的生命周期由servlet来管理 -->
	     <param-name>targetFilterLifecycle</param-name>
	     <param-value>true</param-value>
	  </init-param>
	  <init-param>
	      <!-- 表示在spring容器中bean的id,如果不配置该属性,那么默认和该filter的name一致 -->
	      <param-name>targetBeanName</param-name>
	      <param-value>shiroFilter</param-value>
	  </init-param>
</filter>
<filter-mapping>
     <filter-name>shiroFilter</filter-name>
     <url-pattern>/*</url-pattern>
</filter-mapping>

3.在src下添加applicationContext-shiro.xml

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd" default-autowire="byName">
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	    <!-- 配置securityManager -->
	    <property name="securityManager" ref="securityManager"></property>
	    <!-- 当访问需要认证的资源时,如果没有认证,那么将自动跳转到该url,登陆url 如果不配置该属性会到根路径下的login.jsp-->
	    <property name="loginUrl" value="/login"></property>
	    <!-- 配置认证成功后跳转到那个url上,通常不设置,如果不设置,那么默认认证成功后跳转上上一个url -->
	    <property name="successUrl" value="/index"></property>
	    <!-- 配置用户没有权限访问资源时跳转的页面 -->
	    <property name="unauthorizedUrl" value="/refuse"></property>
	    <!-- 
	             配置shiro的过滤连 
	       logout默认退出后跳转到根目录下,可以重新指定      
	    -->
	    
	    <property name="filterChainDefinitions">
	       <value>
	          /login=anon
	          /login=authc
	          /logout=logout
              /js/**=anon
              /css/**=anon
              /images/**=anon
	          /**=authc
	       </value>
	    </property>
	 
    </bean>	
	 <!-- 配置securityManager -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
         <property name="realm" ref="userRealm"></property>
    </bean>
        <!-- 配置自定义realm -->
    <bean id="userRealm" class="com.bjsxt.realm.UserRealm">
    </bean>
</beans>

4.修改Controller中的login登陆方法

 	//登陆
@RequestMapping("/login")
public ModelAndView login(HttpServletRequest request){
	ModelAndView mv=new ModelAndView("login");
	String className=(String) request.getAttribute("shiroLoginFailure");
    if(UnknownAccountException.class.getName().equals(className)){
    	//抛出自定义异常
    	mv.addObject("msg","用户名或密码错误");
    	
    }else if(IncorrectCredentialsException.class.getName().equals(className)){
    	mv.addObject("msg", "用户名或密码错误");
    }else{
    	mv.addObject("msg", "系统异常");
    }
	return mv;		
}

5.添加自定义Realm:UserRealm

  public class UserRealm extends AuthorizingRealm{
	
	@Override
	public String getName() {
		return "userRealm";
	}

	
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String userName = token.getPrincipal().toString();
		String pwd="1234";
		return new SimpleAuthenticationInfo(userName,pwd,getName());
	}
	
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
	     return null;
	}

二.修改userRealm是实现身份认证

public class UserRealm extends AuthorizingRealm{

@Autowired
private UserService userService;
@Autowired
private Permissionservice permissionservice;

@Override
public String getName() {
	return "userRealm";
}


@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
	String userName = token.getPrincipal().toString();
	User user=userservice.findUserByName(username);
	if(user!=null){
		user.setMenus(permissionService.findByUserId(user.getId()));
	}	
	return new SimpleAuthenticationInfo(userName,pwd,getName());
}

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

	return null;
	
}

三.配置授权

1.在自定义UserRealm中的doGetAuthorizationInfo()方法中

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    //获取身份验证信息 该身份验证信息在认证时已设置
	Users users=(Users)principals.getPrimaryPrincipal();
	//根据userId得到其权限
	List<Permission> permissions=permissionService.findPermissionByUserId(users.getId());
	if(permissions==null||permissions.size()){
		return null;
	}
	SimpleAuthenticationInfo info=new SimpleAuthenticationInfo();
	
	for(Permission p:permissions){
		info.addStringPermission(p.getPercode);
	}
	return info;
	
}

2.想让授权起作用还需要配置两个地方,一个是注解起作用,一个是页面起作用。和在springmvc配置文件中添加aop代理,并且添加异常处理(注解起对权限作用)

<!-- 在springmvc中开启aop代理,并且添加异常处理 -->
<aop:config proxy-target-class="true"></aop:config>
<!-- 开启shiro注解支持 -->
<bean  class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
   <property name="securityManager" ref="securityManager"></property>
</bean>
<!--异常处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolve">
    <property name="exceptionMappings">
       <props>
          <!-- key是异常完全限定名 值是视图名 -->
          <!-- 认证异常 -->
          <prop key="org.apache.shiro.authz.UnauthenticatedException">login</prop>
          <!-- 授权异常 -->
          <prop key="org.apache.shiro.authz.UnauthorizedException">refuse</prop>
       </props>
    </property>
</bean>

3.在jsp页面中,添加按钮权限检查(页面对权限起作用)

  • 首先需要导入shiro的标准库

    <%@ taglib prefix=“shiro” uri=“http://shiro.apache.org/tags”%>

  • 在需要检查权限的地方使用shiro标签
    <!–当前用户有update权限,显示修改操作->
    <shiro:hasPermission name=“role:update”>修改</shiro:hasPermission>

4.在controller方法中添加权限检查注解

   @RequestMapping("/list")
   @RequiresPermissions("Role:list")
    ModelANdView mv=new ModelAndViewe("role/list"){
    mv.addObject("list",roleService.findAll());
    return mv;
   }

四.缓存

1.不能将授权功能放在认证功能中,因为有可能管理员在用户登陆操作时修改用户权限,如果将授权功能放在认证功能中,则只要用户不登出,管理员修改的权限不生效,用户还可操作。

2.但不把授权放在认证中,每次都会去数据库查询权限信息,此时可用缓存处理。写个缓存方法,当管理员修改权限后清理缓存方法

3.每次权限检查都会导数据库中获取权限,这样效率低。可以通过设置缓存来解决该问题。Shiro可以和ehcache或redis集成。

4.步骤

  • 将eacache.jar导入系统

  • shiro默认集成了一个ehcache.xml的配置文件。也可以自己添加一个进行配置,如果自定义配置文件,放在src下。

      <ehcache>		
          <diskStore path="java.io.tmpdir/shiro-ehcache"/>
          <defaultCache
                  maxElementsInMemory="10000"
                  eternal="false"
                  timeToIdleSeconds="120"
                  timeToLiveSeconds="120"
                  overflowToDisk="false"
                  diskPersistent="false"
                  diskExpiryThreadIntervalSeconds="120"
                  />
      </ehcache>
    
  • 在applicationContext-shiro.xml中,添加cacheManager的配置

           <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
               <property name="realm" ref="userRealm"></property>
               <property name="cachemManager" ref="cacheManager"></property>
           </bean>
           <!-- 配置缓存管理器 -->
          <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
             <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
          </bean>
    
  • 如果在运行过程中,主体的权限发生了改变,那么应该从spring容器中调用realm中的清理缓存方法,进行清理

      //清理缓存方法
      /*@Override
      protected void clearCache(PrincipalCollection principals) {
      	super.clearCache(principals);
      }*/
      
      protected void clearCache() {
      	Subject subject = SecurityUtils.getSubject();
      	super.clearCache(subject.getPrincipals());
      }
    

五.会话(session)管理

1.配置securityManager

 <!-- 配置securityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
     <property name="realm" ref="userRealm"></property>
     <property name="cachemManager" ref="cacheManager"></property>
     <property name="sessionManager" ref="sessionManager"></property>
</bean>

2.配置会话管理器

  <!-- 配置会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
   <!-- 单位是毫秒 -->
   <property name="globalSessionTimeout" value="300000"></property>
   <!-- 删除无效session -->
   <property name="deleteInvalidSessions" value="true"></property>
</bean>

六.记住我

1.将用户类实现序列化接口,该类的引用类也必须实现序列化接口

2.设置登陆时表单中“记住我”的域名

 <!-- 配置authc过滤器 -->
 <bean id="authc" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
      <property name="usernameParam" value="name"></property>
      <property name="passwordParam" value="pwd"></property>
      <property name="rememberMeParam" value="rememberMe"></property>
 </bean>

3.设置“记住我”管理器

    <!-- 配置securityManager -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
         <property name="realm" ref="userRealm"></property>
         <property name="cachemManager" ref="cacheManager"></property>
         <property name="sessionManager" ref="sessionManager"></property>
         <property name="rememberMeManager" ref="rememberMeManager"></property>
    </bean>

    <!-- 记住我配置 -->
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <property name="cookie" ref="rememberMeCookie"></property>
    </bean>
    <!-- 记住我cookie -->
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <!-- 设置cookie的存活时间 -->
        <property name="maxAge" value="604800"></property>
        <!-- 设置cookie名称 -->
        <property name="name" value="rememberMe"></property>
    </bean>

4.在过滤链中配置哪些资源通过记住我可以再次访问

     <property name="filterChainDefinitions">
       <value>
          /login=anon
          /login=authc
          /logout=logout
          /js/**=anon
          /css/**=anon
          /index=user
          /images/**=anon
          /**=authc
       </value>
    </property>

5.页面设置

  <input type="checkbox" name="rememberMe">
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值