1.整合准备
企业中老项目还在使用ssm框架。
(1)创建一个maven的web工程。
(2)ssm整合到web工程----省略
spring配置文件
<?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" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 包扫描 --> <context:component-scan base-package="com.wzh"/> <!-- 开启注解 --> <mvc:annotation-driven /> <!-- 静态资源放行 --> <mvc:default-servlet-handler/> <!-- 启动Shrio的注解 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.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> <!-- 德鲁伊连接池 --> <bean id="dataResource" class="com.alibaba.druid.pool.DruidDataSource"> <!--驱动名称--> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/shiro?serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="123456"/> <!--初始化连接池的个数--> <property name="initialSize" value="10"/> <!--至少的个数--> <property name="minIdle" value="5"/> <!--最多的个数--> <property name="maxActive" value="10"/> <!--最长等待时间单位毫秒--> <property name="maxWait" value="2000"/> </bean> <!--创建事务管理类--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataResource"/> </bean> <!--开启事务注解--> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- sqlSessionFactoryBean --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataResource"/> <!-- 配置映射文件 --> <property name="mapperLocations" value="classpath:mapper/*.xml"/> <!-- 配置分页 --> <property name="plugins" > <array> <bean class="com.github.pagehelper.PageInterceptor"/> </array> </property> </bean> <!--dao接口的代理实现类--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.wzh.mapper"/> </bean> <!--下面是shiro中需要加的--> <!--整合shiro的配置内容--> <!--1、配置securityManager--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="realm"/> </bean> <!--2、配置自定义的Realm--> <bean id="realm" class="com.wzh.realm.MyRealm"> <property name="credentialsMatcher" ref="credentialsMatcher"/> </bean> <!--3、创建密码匹配器--> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="MD5"/> <property name="hashIterations" value="1024"/> </bean> <!--shiro过滤工厂: 设置过滤的规则--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- Shiro的核心安全接口,这个属性是必须的 --> <property name="securityManager" ref="securityManager"/> <!--设置未登录的跳转路径--> <!-- <property name="loginUrl" value="/login.jsp"/>--> <!--设置没有权限的跳转路径--> <!-- <property name="unauthorizedUrl" value="/unauthorizedUrl.jsp"/>--> <!--设置过滤器--> <property name="filterChainDefinitions"> <value> /login=anon /**=authc </value> </property> <!--未登录 过滤器--> <property name="filters"> <map> <entry key="authc"> <!--自定义过滤器所在的路径--> <bean class="com.wzh.filter.LoginFilter"/> </entry> </map> </property> </bean> </beans>
web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--shiro过滤器的代理--> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 注册servlet --> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 解决中文乱码 注册文字格式拦截器 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
pom依赖
<dependencies> <!--spring-webmvc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.15.RELEASE</version> </dependency> <!--mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <!--mybatis和spring整合的依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.6</version> </dependency> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <!--druid连接池依赖--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.1</version> </dependency> <!--lombok依赖--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency> <!--jackson java对象转换为json对象 @ResponseBody--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.2.2</version> </dependency> <!--servlet-api依赖--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.15.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.2.15.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.15.RELEASE</version> </dependency> <!--generator--> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.0</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
数据库数据结构:
张三 -user:query user:add user:update user:delete
李四 ---》user:query user:add user:update王五-----》user:query user:export
数据库:
SSM环境的搭建
shiro的整合
(1)引入shiro依赖
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.9.0</version>
</dependency>
(2)修改spring配置文件
<!--整合shiro的配置内容-->
<!--①SecurityManager-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="realm"/>
</bean>
<!--创建自定义realm类对象-->
<bean id="realm" class="com.ykq.realm.MyRealm">
<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="1024"/>
</bean>
<!--shiro过滤工厂: 设置过滤的规则-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!--如果没有登录,跳转的路径-->
<property name="loginUrl" value="/login.jsp"/>
<!--没有权限,跳转的路径-->
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<property name="filterChainDefinitions">
<value>
/login=anon
/**=authc
</value>
</property>
</bean>
shiro中内置很多过滤器,而每个过滤都有相应的别名.
(3) 修改web.xml文件
<!--shiro过滤器的代理-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.1 进入主页后,不同的用户可以看到不同的内容。
<%--
Created by IntelliJ IDEA.
User: YSH
Date: 2022/8/5
Time: 16:50
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head>
<title>登录成功界面</title>
</head>
<body>
<h1>欢迎来<shiro:principal property="username"/>到主页</h1>
<shiro:hasPermission name="/user/query">
<a href="/user/query">查询用户信息</a><br>
</shiro:hasPermission>
<shiro:hasPermission name="/user/delete">
<a href="/user/delete">删除用户信息</a><br>
</shiro:hasPermission>
<shiro:hasPermission name="/user/update">
<a href="/user/update">修改用户信息</a><br>
</shiro:hasPermission>
<shiro:hasPermission name="/user/insert">
<a href="/user/insert">增加用户信息</a><br>
</shiro:hasPermission>
<shiro:hasPermission name="/user/export">
<a href="/user/export">导出用户信息</a><br>
</shiro:hasPermission>
</body>
</html>
可以在jsp中获取当前登录者的账号
<h1>欢迎<shiro:principal property="username"/>来到主页</h1>
上面只是在网页中根据不同用户显示不同的菜单,这种方式只能防君子不能防小人。因为现在依旧可以通过postman访问没有的权限方法 比如张三可以访问到user:export路径
解决办法:
拦截器---获取请求路径 然后根据你的路径判断当前用户是否具有该权限。
2 .spring整合shiro时提供了一个注解:可以加载相应方法上。
2.1
1.在springmvc中开启shiro注解 <!-- 启动Shrio的注解 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.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>
2.2在controller层使用shiro注解
@RequiresPermissions(value = {"/user/query","/user/aaa"},logical= Logical.OR)
这个太丑了,我们想要跳转一个页面,
我们之前学过全局异常处理: 没有登录会报这个异常
2.ssm整合shiro完成前后端分离
所谓前后端完全分离:后端响应的都是json数据,而不再是网页。
1. 登录成功或者失败应该返回json数据
2. 当未登录时返回的也是json数据
3. 访问未授权的资源,也要分会json。
2.1 登录成功或者失败应该返回json数据
修改登录接口
2.2 当未登录时返回的也是json数据
创建一个过滤器,继承登录校验的某个接口。
package com.qy151.filter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qy151.until.CommonResult;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.PrintWriter;
/**
* @BelongsProject: 0804-ssm-shiro
* @BelongsPackage: com.qy151.filter
* @unthor : YSH
* @date : 2022/8/5 17:46
* @Description: TODO
*/
public class LoginFilter extends FormAuthenticationFilter {
//当没有登录时会经过该方法。如果想让他返回json数据那么必须重写方法
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
//未登录时的状态信息
CommonResult commonResult = new CommonResult(4001, "未登录,请先登录", null);
//把java对象转换为json数据
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(commonResult);
writer.print(json);//响应给客户json数据
writer.flush();
writer.close();
return false;
}
}
(2)注册我们的过滤器