SSM集成Shiro

SSM整合Shiro

1. 添加pom依赖

<dependency>
	      <groupId>commons-logging</groupId>
	      <artifactId>commons-logging</artifactId>
	      <version>1.2</version>
	    </dependency>
	    <dependency>
	      <groupId>org.slf4j</groupId>
	      <artifactId>slf4j-nop</artifactId>
	      <version>1.7.24</version>
	    </dependency>
	    <dependency>
	      <groupId>commons-collections</groupId>
	      <artifactId>commons-collections</artifactId>
	      <version>3.2.1</version>
	    </dependency>
	    <dependency>
	      <groupId>org.apache.shiro</groupId>
	      <artifactId>shiro-core</artifactId>
	      <version>1.4.0</version>
	    </dependency>
	    <dependency>
	      <groupId>org.apache.shiro</groupId>
	      <artifactId>shiro-web</artifactId>
	      <version>1.4.0</version>
	    </dependency>
	    <dependency>
	      <groupId>org.apache.shiro</groupId>
	      <artifactId>shiro-ehcache</artifactId>
	      <version>1.4.0</version>
	    </dependency>
	    <dependency>
	      <groupId>org.apache.shiro</groupId>
	      <artifactId>shiro-spring</artifactId>
	      <version>1.4.0</version>
	    </dependency>

2. 在web.xml中配置过滤器拦截所有请求

<!-- 拦截到所有请求,使用spring一个bean来进行处理 -->
	    <filter>
	        <filter-name>shiroFilter</filter-name>
	        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	        <!-- 是否filter中的init和 destroy-->
	        <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>

3. 新建shiro配置文件并在spring的核心配置文件中引入(文末附有整个shiro.xml)

 <!-- 配置shiro过滤器 -->
	    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	        <property name="securityManager" ref="securityManager"></property>
	
	        <!-- 配置shiro过滤器pattern -->
	        <property name="filterChainDefinitions">
	            <value>
	                /static/** = anon   <!--不需要登录验证-->
	                /login.jsp = anon   <!--不需要登录验证-->
	                /**=authc     <!--除指定请求外,其它所有的请求都需要身份验证-->
	            </value>
	        </property>
	    </bean>
	
	    <!-- 配置shiro安全管理器 -->
	    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"></bean>

spring的核心配置文件中:

<import resource="classpath:application-shiro.xml"/>

4. 登录认证
1)表单发送请求

2 ) 在Application-shiro.xml中指定登录认证
(这里的/login是第1步中发送post请求的url)

<!-- 配置登录认证的路径 --> <property name="loginUrl" value="/login" />

(写到这里项目在执行请求的时候会判断是不是login请求,如果不是,再判断有没有认证过,如果没有认证,执行对应的login请求,跳转到login.jsp页面(因为在controller中写了跳转方法)。如果执行的是login请求,就会做认证,下面写认证方法)

5. 创建登录realm(新建一个realm的包,再创建一个XXXRealm的类(这里我创建的是EmployeeRealm),这个类要继承AuthorizingRealm,并且实现里面的方法)
在这里插入图片描述
在application-shiro.xml中自定义并且注入realm:
在这里插入图片描述
实现认证:
在这里插入图片描述

6. 创建过滤器(监听认证成功了还是失败了,创建一个包filter,并且创建类MyFormFilter继承FormAuthenticationFilter)在这里插入图片描述
在application-shiro.xml中配置:

(写到这的时候,点击登录的时候,如果用户名密码正确的时候就会到过滤器中onLoginSuccess方法,用户名或密码错误就会调用onLoginFailure方法)

登录成功相应给浏览器:
在这里插入图片描述
登录失败方法:
在这里插入图片描述

login请求:

7. 退出功能
登录成功显示用户名:
退出登录(在shiro.xml中写注销路径)
在这里插入图片描述

(写到这,用户名密码正确的时候可以成功跳到主页并显示用户名,点击注销的时候返回到登录页面。登录完成)


8. 授权
(当我们在控制器方法写了@RequiresPermissions,shiro在访问时,就会判断有没有该权限,如果没有,就不会执行对应方法)

1)在application-shiro配置文件中添加shiro注解

<!--
		    配置为true即使用cglib继承的方式,
		    false为jdk的接口动态代理   控制器没有实现接口;
		    -->
		    <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>

2)在controller类的方法中添加@RequiresPermissioins

3)授权调用:
在这里插入图片描述

/*授权
    web  doGetAuthorizationInfo什么时候调用
    1.发现访问路径对应的方法上面 有授权注解 就会调用doGetAuthorizationInfo
    2.页面当中有授权标签,也会调用doGetAuthorizationInfo
    * */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授权调用------------");
        /*获取用户的身份信息*/
        Employee employee = (Employee) principalCollection.getPrimaryPrincipal();
        /*根据当前用户,查询角色和权限*/
        List<String> roles = new ArrayList<>();
        List<String> permissions = new ArrayList<>();

        /*判断当前用户是不是管理员 如果是管理员 拥有所有的权限*/
        if(employee.getAdmin()){
            /*拥有所有的权限*/
            permissions.add("*:*");
        }else {
            /*查询角色*/
            roles = employeeService.getRolesById(employee.getId());
            /*查询权限*/
            permissions = employeeService.getPermissionbyId(employee.getId());//查询角色和权限的方法省略

        }
        /*给授权信息*/
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roles);
        info.addStringPermissions(permissions);

        return info;
    }

(写到这调用某一接口时,如果该用户(我这里是管理员有所有权限)有此权限,就会执行相应的方法)

9. 没有权限处理
在controller中写一个方法处理shiro异常

 /*异常处理方法*/
    @ExceptionHandler(AuthorizationException.class)
    public void handleShiroException(HandlerMethod method, HttpServletResponse response) throws Exception { /*method是发生异常的方法*/
        /*跳转到一个界面 界面提示没有权限*/
        /*判断 当前的请求是不是json请求  如果是 返回json给浏览器 让它自己来做跳转*/

        /*获取方法上的注解*/
        ResponseBody methodAnnotation = method.getMethodAnnotation(ResponseBody.class);
        if(methodAnnotation != null){
            //ajax
            AjaxRes ajaxRes = new AjaxRes();
            ajaxRes.setSuccess(false);
            ajaxRes.setMsg("您没有权限操作呢");
            /*把对象转成json格式字符串*/
            String jsonString = new ObjectMapper().writeValueAsString(ajaxRes);
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(jsonString);

        }else{
            response.sendRedirect("nopermission.jsp");
        }

    }

新建一个nopermission.jsp,告诉用户没有权限

10.权限按钮控制
在controller中的方法上添加对应的权限,例如:

在需要权限控制的地方添加对应的shiro标签(记得引入shiro标签库

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

在这里插入图片描述
(写到这调用某一接口时,如果该用户没有此权限,就会告诉用户没有权限,没有权限的标签不会显示出来)

11.散列密码加密

1)在保存用户的时候把密码进行加密
在这里插入图片描述
2)在认证中添加密码处理
在这里插入图片描述
3)添加凭证匹配器
在这里插入图片描述

12.授权缓存添加
(进入页面时, 页面当中写了Shiro的标签,每一个标签都要去到授权当中进行一次授权查询。授权查询只使用一次即可, 所以使用缓存,把对应的内容缓存起来,下次再去, 直接从缓存当中进行查询)
1)添加缓存pom依赖

<dependency>
		      <groupId>org.apache.shiro</groupId>
		      <artifactId>shiro-ehcache</artifactId>
		      <version>1.2.2</version>
		    </dependency>

2)添加shiro-ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 	xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"> 	<defaultCache  		maxElementsInMemory="1000"  		maxElementsOnDisk="10000000" 		eternal="false"  		overflowToDisk="false"  		diskPersistent="false" 		timeToIdleSeconds="120" 		timeToLiveSeconds="120"  		diskExpiryThreadIntervalSeconds="120" 		memoryStoreEvictionPolicy="LRU"> 	</defaultCache> </ehcache>

配置约束
在这里插入图片描述

3)application-shiro中配置缓存管理器

<!-- 缓存管理器 -->
			    <bean id="ehCache" class="org.apache.shiro.cache.ehcache.EhCacheManager">
			        <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
			    </bean>

在这里插入图片描述
4)把缓存管理器添加到安全管理器当中

<!-- 配置shiro安全管理器 -->
			    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
			        <property name="realm" ref="employeeRealm" />
			        <property name="cacheManager" ref="ehCache"/>
			    </bean>

在这里插入图片描述
附录:
application-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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
     http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
">
    <bean id="myFormFilter" class="com.lyd.web.filter.MyFormFilter"/>

    <!-- 配置shiro过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--
        其他的请求 会判断有没有认证过

        index
        默认情况下 : 没有认证,会自动跳转到login.jsp
        配置了loginUrl : 如果没有认证,就会执行对应的login请求

        login:
        loginUrl:如果发现请求是loginUrl的值 会去做认证

        配置登录认证的路径
        -->
        <property name="loginUrl" value="/login" />

        <!--配置表单监听的过滤器-->
        <property name="filters">
            <map>
                <entry key="authc" value-ref="myFormFilter"/>
            </map>
        </property>

        <property name="securityManager" ref="securityManager"></property>

        <!-- 配置shiro过滤器pattern -->
        <property name="filterChainDefinitions">
            <value>
                /static/** = anon   <!--不需要登录验证-->
                /login.jsp = anon   <!--不需要登录验证-->
                /logout = logout    <!--取消认证-->
                /**=authc     <!--除指定请求外,其它所有的请求都需要身份验证-->
            </value>
        </property>
    </bean>

    <!--自定义realm-->
    <bean id="employeeRealm" class="com.lyd.web.realm.EmployeeReam">
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
    </bean>

    <!-- 凭证匹配器 -->
    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <!-- 散列算法 -->
        <property name="hashAlgorithmName" value="md5"/>
        <!-- 散列次数 -->
        <property name="hashIterations" value="2"></property>
    </bean>

    <!-- 缓存管理器 -->
    <bean id="ehCache" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
    </bean>


    <!-- 配置shiro安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--注入realm-->
        <property name="realm" ref="employeeRealm"/>
        <!--注入缓存-->
        <property name="cacheManager" ref="ehCache"/>

    </bean>

    <!--
	    配置为true即使用cglib继承的方式,
	    false为jdk的接口动态代理   控制器没有实现接口
	    -->
    <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>


</beans>

发布了31 篇原创文章 · 获赞 13 · 访问量 1431

猜你喜欢

转载自blog.csdn.net/weixin_44210965/article/details/89390026
今日推荐