1.完成ssm整合shiro
企业中老项目还在使用ssm框架。
准备数据库

数据结构
张三 -user:query user:add user:update user:delete
李四 ---》user:query user:add user:update
王五-----》user:query user:export

搭建ssm的环境
(1)创建一个maven的web工程。
(2)ssm整合到web工程
1.pom依赖
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>ssm-shiro1029</artifactId><version>1.0-SNAPSHOT</version> <!--版本和依赖分离--><properties><spring.version>5.2.15.RELEASE</spring.version></properties><dependencies><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.9.0</version></dependency><!--spring-webmvc--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</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></project>2.spring配置文件(spring和springmvc配置在一起)
<?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/><!--视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="WEB-INF/views/"/><property name="suffix" value=".jsp"/></bean><!-- 启动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>3.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>
上面是spring和springmvc配置文件在一起的,有的时候spring配置文件和springmvc文件没有在一起,如下
application.xml---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.service"/><!--导入db.properties--><!--引入属性文件--><context:property-placeholder location="classpath:db.properties"/><!--配置数据源--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!--SqlSessionFactoryBean--><bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="mapperLocations" value="classpath:mapper/*.xml"/></bean><!--为Dao生成实现类--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.wzh.dao"/></bean><!--事务--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!--开启事务注解--><tx:annotation-driven transaction-manager="transactionManager"/> </beans>springmvc.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"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.controller"/><!--静态资源放行--><mvc:default-servlet-handler/><!--注解驱动--><mvc:annotation-driven/><!--视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="WEB-INF/views/"/><property name="suffix" value=".jsp"/></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"><!--监听器 加载spring配置文件--><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:application.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 前端控制器 加载springmvc配置文件--><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>4.mapper.xml配置
<?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.wzh.mapper.PermissionMapper"></mapper>controller service dao entity文件夹创建 省略,
5.登录页面和成功页面准备好
整合shiro
(1)引入shiro的依赖
<!--shiro--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.9.0</version></dependency>
(2)spring的配置文件添加shiro的配置

<?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.service"/><!--导入db.properties--><!--引入属性文件--><context:property-placeholder location="classpath:db.properties"/><!--配置数据源--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!--SqlSessionFactoryBean--><bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="mapperLocations" value="classpath:mapper/*.xml"/></bean><!--为Dao生成实现类--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.wzh.dao"/></bean><!--事务--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!--开启事务注解--><tx:annotation-driven transaction-manager="transactionManager"/><!--spring整合shiro--><!--SecurityManager的管理--><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="myRealm"/></bean><!--创建Realm对象--><bean id="myRealm" class="com.wzh.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的过滤器链id:后面要求必须和web.xml中的配置名称相同--><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><!--设置安全管理对象--><property name="securityManager" ref="securityManager"/><!--如果没有认证 则跳转到登录页面--><property name="loginUrl" value="/toLogin"/><!--如果没有权限,跳转的路径--><property name="unauthorizedUrl" value="/unauthorizedUrl.jsp"/><!--过滤器链--><!--anon:表示允许匿名访问authc:需要认证后才可以访问--><property name="filterChainDefinitions"><value>/index.jsp=anon/login=anon/**=authc</value></property></bean></beans>
如果jsp文件都在webapp下,并没有在WEB-INF下的views中设置如下:
<!--整合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文件
<?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><!--该名称必须和ShiroFilterFactoryBean的id相同(也就是spring配置文件中的ShiroFilterFactoryBean)--><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><!--监听器 加载spring配置文件--><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:application.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 前端控制器 加载springmvc配置文件--><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>
(4)controller
package com.wzh.controller;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;/*** @ProjectName: ssm-shiro-1029* @Package: com.wzh.controller* @ClassName: PageController* @Author: 王振华* @Description:* @Date: 2022/10/29 19:07* @Version: 1.0*/
@Controller
public class PageController {@GetMapping("/toLogin")public String toLogin(){return "login";//经过视图解析器,找到WEB-INF/views下}@ResponseBody@RequestMapping("login")public String login(String username, String password) {System.out.println(username);//获取subject主体对象Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken(username, password);try {subject.login(token);return "success";} catch (Exception e) {e.printStackTrace();return "fail";}}
}
(5) myRealm
package com.wzh.realm;import com.wzh.pojo.entity.User;
import com.wzh.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.apache.shiro.util.ByteSource;import java.util.List;/*** @ProjectName: maven-shiro1028* @Package: com.wzh.realm* @ClassName: MyRealm* @Author: 王振华* @Description:* @Date: 2022/10/28 19:07* @Version: 1.0*/
public class MyRealm extends AuthorizingRealm {private UserService userService = new UserService();//授权时执行该方法@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;}//认证时执行该方法@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("认证方法=====");//1.获取登录者的账号String username = authenticationToken.getPrincipal().toString();//2.根据账号查询数据库User user = userService.findByUsername(username);if(user!=null){//Object principal,账号数据库中// Object credentials,密码数据库中//ByteSource credentialsSalt 使用的盐// String realmName realm的名称随便起//密码的比对交于SimpleAuthenticationInfo//未来在数据中一列设置为存放盐ByteSource salt = ByteSource.Util.bytes(user.getSalt());SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getUserpwd(),salt,this.getName());return info;}return null;}
}
(6)service
package com.wzh.service;import com.wzh.dao.UserMapper;import com.wzh.pojo.entity.User;
import com.wzh.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/*** @ProjectName: ssm-shiro* @Package: com.wzh.service.impl* @ClassName: UserServiceImpl* @Author: 王振华* @Description:* @Date: 2022/8/4 22:20* @Version: 1.0*/
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public User findByUsername(String username) {if(username!=null&&username!="") {User user = userMapper.selectByUsername(username);return user;}return null;}}
(7)userMapper.xml,dao层省略
<?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.wzh.dao.UserMapper"><select id="selectByUsername" resultType="com.wzh.pojo.entity.User">select * from user where username = #{username}</select>
</mapper>
1.1. 进入主页后,不同的用户可以看到不同的内容。
<%--Created by IntelliJ IDEA.User: m1762Date: 2022/8/4Time: 22:58To 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</title>
</head>
<body><shiro:hasPermission name="user:query"><a href="/query">查询用户</a></shiro:hasPermission><shiro:hasPermission name="user:add"><a href="/add">添加用户</a></shiro:hasPermission><shiro:hasPermission name="user:delete"><a href="/delete">删除用户</a></shiro:hasPermission><shiro:hasPermission name="user:update"><a href="/update">修改用户</a></shiro:hasPermission><shiro:hasPermission name="user:export"><a href="/export">导出用户</a></shiro:hasPermission>
</body>
</html>

可以在jsp中获取当前登录者的账号
<h1>欢迎<shiro:principal property="username"/>来到主页</h1>

上面只是在网页中根据不同用户显示不同的菜单,这种方式只能防君子不能防小人。因为现在依旧可以通过postman访问没有的权限方法 比如张三可以访问到user:export路径
解决办法:
拦截器---获取请求路径 然后根据你的路径判断当前用户是否具有该权限。
spring整合shiro时提供了一个注解:可以加载相应方法上。
使用注解:
1.springmvc.xml中启动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.ssm整合shiro完成前后端分离
所谓前后端完全分离:后端响应的都是json数据,而不再是网页。
我们需要修改的就是:
1. 登录成功或者失败应该返回json数据
2. 当未登录时返回的也是json数据
3. 访问未授权的资源,也要分会json。
2.1.登录成功或者失败应该返回json数据
修改登录接口

2.2 当未登录时返回的也是json数据
(1)创建一个过滤器,继承登录校验的FormAuthenticationFilter接口。
package com.wzh.filter;import com.fasterxml.jackson.databind.ObjectMapper;
import com.wzh.utils.CommonResult;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.PrintWriter;/*** @ProjectName: shiro-ssm0805* @Package: com.wzh.filter* @ClassName: LoginFilter* @Author: 王振华* @Description:* @Date: 2022/8/5 16:58* @Version: 1.0*/
public class LoginFilter extends FormAuthenticationFilter {/*** 当没有登录时会经过该方法,如果想让它返回json数据必须重写onAccessDenied这个方法* @param request* @param response* @return* @throws Exception*/@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {response.setContentType("application/json;charset=utf-8");PrintWriter writer = response.getWriter();CommonResult commonResult = CommonResult.UNLOGIN;//jackson中内置对象 将java对象转为json对象ObjectMapper objectMapper = new ObjectMapper();String json = objectMapper.writeValueAsString(commonResult);//响应给客户json数据writer.print(json);writer.flush();writer.close();return false;}
}
之前默认是在springmvc.xml中配置的跳转页面

(2) 注册我们的过滤器

2.3 如果没有权限应该返回json数据

3.项目完整代码
项目结构:

Controller层:
UserController: 用于登录 调用login方法判断是否身份认证 授权
package com.wzh.controller;import com.wzh.utils.CommonResult;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @ProjectName: ssm-shiro* @Package: com.wzh.controller* @ClassName: UserController* @Author: 王振华* @Description:* @Date: 2022/8/4 22:07* @Version: 1.0*/
@RestController
public class UserController {@RequestMapping("login")public CommonResult login(String username,String password){System.out.println(username);//获取subject主体对象Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken(username, password);try{subject.login(token);System.out.println("是否身份认证:"+subject.isAuthenticated());System.out.println("是否授权:"+subject.isPermitted("查询"));System.out.println("是否授权:"+subject.isPermitted("添加"));System.out.println("是否授权:"+subject.isPermitted("修改"));System.out.println("是否授权:"+subject.isPermitted("删除"));System.out.println("是否授权:"+subject.isPermitted("导出"));System.out.println("是否授权:"+subject.hasRole("超级管理员"));System.out.println("是否授权:"+subject.hasRole("管理员"));System.out.println("是否授权:"+subject.hasRole("用户"));return CommonResult.LOGIN_SUCCESS;}catch (Exception e){e.printStackTrace();return CommonResult.LOGIN_ERROR;}}
}
PermissionController: 用于登录之后查看是否授权
package com.wzh.controller;import com.wzh.utils.CommonResult;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @ProjectName: shiro-ssm0805* @Package: com.wzh.controller* @ClassName: PermissionController* @Author: 王振华* @Description:* @Date: 2022/8/5 9:57* @Version: 1.0*/
@RestController
public class PermissionController {@GetMapping("/query")//使用shiro注解@RequiresPermissions(value = {"user:query","user:aaa"},logical = Logical.OR)public String query(){return "query";}@RequestMapping("/add")@RequiresPermissions(value = {"user:add"})public String add(){return "add";}@RequestMapping("/delete")@RequiresPermissions(value = {"user:delete"})public String delete(){return "delete";}@RequestMapping("/update")@RequiresPermissions(value = {"user:update"})public String update(){return "update";}@RequestMapping("/export")@RequiresPermissions(value = {"user:export"})public String export(){return "export";}
}
service层:
UserService:
package com.wzh.service;import com.wzh.entity.User;import java.util.List;/*** @ProjectName: ssm-shiro* @Package: com.wzh.service* @ClassName: UserService* @Author: 王振华* @Description:* @Date: 2022/8/4 22:19* @Version: 1.0*/
public interface UserService {User findByUsername(String username);}
PermissionService:
package com.wzh.service;import java.util.List;/*** @ProjectName: ssm-shiro* @Package: com.wzh.service* @ClassName: PermissionService* @Author: 王振华* @Description:* @Date: 2022/8/4 22:27* @Version: 1.0*/
public interface PermissionService {List<String> findPermissionById(Integer userid);
}
RoleService:
package com.wzh.service;import java.util.List;/*** @ProjectName: ssm-shiro* @Package: com.wzh.service* @ClassName: RoleService* @Author: 王振华* @Description:* @Date: 2022/8/4 22:27* @Version: 1.0*/
public interface RoleService {List<String> findRolesById(Integer userid);
}
UserServiceImpl:
package com.wzh.service.impl;import com.wzh.entity.User;
import com.wzh.mapper.UserMapper;
import com.wzh.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/*** @ProjectName: ssm-shiro* @Package: com.wzh.service.impl* @ClassName: UserServiceImpl* @Author: 王振华* @Description:* @Date: 2022/8/4 22:20* @Version: 1.0*/
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic User findByUsername(String username) {if(username!=null&&username!="") {User user = userMapper.selectByUsername(username);return user;}return null;}}
PermissionServiceImpl:
package com.wzh.service.impl;import com.wzh.mapper.PermissionMapper;
import com.wzh.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;/*** @ProjectName: ssm-shiro* @Package: com.wzh.service.impl* @ClassName: PermissionServiceImpl* @Author: 王振华* @Description:* @Date: 2022/8/4 22:28* @Version: 1.0*/
@Service
public class PermissionServiceImpl implements PermissionService {@Autowiredprivate PermissionMapper permissionMapper;@Overridepublic List<String> findPermissionById(Integer userid) {List<String> list = permissionMapper.selectByUserId(userid);return list;}
}
RoleServiceImpl:
package com.wzh.service.impl;import com.wzh.mapper.RoleMapper;
import com.wzh.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/*** @ProjectName: ssm-shiro* @Package: com.wzh.service.impl* @ClassName: RoleServiceImpl* @Author: 王振华* @Description:* @Date: 2022/8/4 22:28* @Version: 1.0*/
@Service
public class RoleServiceImpl implements RoleService {@Autowiredprivate RoleMapper roleMapper;@Overridepublic List<String> findRolesById(Integer userid) {List<String> list = roleMapper.selectByUserId(userid);return list;}
}
mapper层:
UserMapper:
package com.wzh.mapper;import com.wzh.entity.User;import java.util.List;/*** @ProjectName: ssm-shiro* @Package: com.wzh.mapper* @ClassName: UserMapper* @Author: 王振华* @Description:* @Date: 2022/8/4 22:21* @Version: 1.0*/
public interface UserMapper {User selectByUsername(String username);}
PermissionMapper:
package com.wzh.mapper;import java.util.List;/**@ProjectName: ssm-shiro
@Package: com.wzh.mapper
@ClassName: PermissionMapper
@Author: 王振华
@Description:
@Date: 2022/8/4 22:21
@Version: 1.0
*/
public interface PermissionMapper {List<String> selectByUserId(Integer userid);
}
RoleMapper:
package com.wzh.mapper;import java.util.List;/*** @ProjectName: ssm-shiro* @Package: com.wzh.mapper* @ClassName: RoleMapper* @Author: 王振华* @Description:* @Date: 2022/8/4 22:21* @Version: 1.0*/public interface RoleMapper {List<String> selectByUserId(Integer userid);
}
entity层:
User:
package com.wzh.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import javax.management.relation.Role;/*** @ProjectName: ssm-shiro* @Package: com.wzh.entity* @ClassName: User* @Author: 王振华* @Description:* @Date: 2022/8/4 22:19* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Integer userid;private String username;private String userpwd;private String sex;private String address;private String salt;private Permission permission;private Role role;
}
Permission:
package com.wzh.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @ProjectName: ssm-shiro* @Package: com.wzh.entity* @ClassName: Permission* @Author: 王振华* @Description:* @Date: 2022/8/4 22:22* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Permission {private Integer perid;private String pername;private String percode;
}
Role:
package com.wzh.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @ProjectName: ssm-shiro* @Package: com.wzh.entity* @ClassName: Role* @Author: 王振华* @Description:* @Date: 2022/8/4 22:22* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Role {private Integer roleid;private String rolename;
}
filter:
LoginFilter: 用于未登录返回json数据
package com.wzh.filter;import com.fasterxml.jackson.databind.ObjectMapper;
import com.wzh.utils.CommonResult;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.PrintWriter;/*** @ProjectName: shiro-ssm0805* @Package: com.wzh.filter* @ClassName: LoginFilter* @Author: 王振华* @Description:* @Date: 2022/8/5 16:58* @Version: 1.0*/
public class LoginFilter extends FormAuthenticationFilter {/*** 当没有登录时会经过该方法,如果想让它返回json数据必须重写onAccessDenied这个方法* @param request* @param response* @return* @throws Exception*/@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {response.setContentType("application/json;charset=utf-8");PrintWriter writer = response.getWriter();CommonResult commonResult = CommonResult.UNLOGIN;//jackson中内置对象 将java对象转为json对象ObjectMapper objectMapper = new ObjectMapper();String json = objectMapper.writeValueAsString(commonResult);//响应给客户json数据writer.print(json);writer.flush();writer.close();return false;}
}
handler: 全局异常处理类 用户没有权限返回json数据给前端
MyException:
package com.wzh.handler;import com.wzh.utils.CommonResult;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;/*** @ProjectName: shiro-ssm0805* @Package: com.wzh.handler* @ClassName: MyException* @Author: 王振华* @Description:* @Date: 2022/8/5 16:42* @Version: 1.0*/
@ControllerAdvice //异常处理类
public class MyException {//当发生该异常时触发该方法@ExceptionHandler(value = UnauthorizedException.class)@ResponseBodypublic CommonResult Unauth(UnauthorizedException e){e.printStackTrace();return CommonResult.UNAUTHORIZED;}
}
realm: 自定义的认证授权规则
MyRealm:
package com.wzh.realm;import com.wzh.entity.User;
import com.wzh.service.PermissionService;
import com.wzh.service.RoleService;
import com.wzh.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** @ProjectName: shiro* @Package: com.wzh.demo02* @ClassName: MyRealm* @Author: 王振华* @Description:* @Date: 2022/8/4 19:44* @Version: 1.0*/
public class MyRealm extends AuthorizingRealm {@Autowiredprivate UserService userService;@Autowiredprivate PermissionService permissionService;@Autowiredprivate RoleService roleService;@Override//该方法用于完成认证的功能protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {//1.根据token获取账号String username = (String) authenticationToken.getPrincipal();/*** 以前登陆的逻辑是 把用户和密码全部发到数据库 去匹配* 在shrio里面是先根据用户名把用户对象查询出来,再来做密码匹配*///2.根据账号查询用户信息User user = userService.findByUsername(username);//表示该用户名在数据库中存在if(user!=null){/*** 参数说明* 参数1:可以传到任意对象* 参数2:从数据库里面查询出来的密码* 参数3:盐* 参数4:当前类名*/ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getUserpwd(),credentialsSalt,this.getName());return info;}//用户不存在 shiro会抛 UnknowAccountExceptionreturn null;}//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {User user = (User) principalCollection.getPrimaryPrincipal();SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//根据账号查找该用户具有哪些权限List<String> list = permissionService.findPermissionById(user.getUserid());if(list!=null&&list.size()>0){info.addStringPermissions(list);}List<String> roles = roleService.findRolesById(user.getUserid());if(roles!=null&&roles.size()>0){info.addRoles(roles);}return info;}}
util:
CommonResult:
package com.wzh.utils;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @ProjectName: shiro-ssm0805* @Package: com.wzh.utils* @ClassName: CommonResult* @Author: 王振华* @Description:* @Date: 2022/8/5 11:02* @Version: 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResult {public static final CommonResult UNLOGIN = new CommonResult(403,"未登录",null);public static final CommonResult UNAUTHORIZED = new CommonResult(405,"未授权",null);public static final CommonResult LOGIN_SUCCESS = new CommonResult(200,"登录成功",null);public static final CommonResult LOGIN_ERROR = new CommonResult(-1,"登录失败",null);private Integer code;private String msg;private Object data;}





















