一、shiro的web流程

二、Shiro整合SSM
新建一个maven项目ssm,pom如下:
xml
<?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>com.simon</groupId>
<artifactId>shiro-web-ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
</dependencies>
<!--<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>-->
</project>
项目整体结构如下:
web.xml
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整合web的过滤器-->
<filter>
<!-- 默认情况下,请求到达这个过滤器,会去Spring容器中名字为filter-name的实例去处理-->
<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-name>springmvc</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>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-*.xml</param-value>
</context-param>
</web-app>
applicationContext-mapper.xml
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"
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">
<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>
<bean class="org.mybatis.spring.SqlSessionFactoryBean" >
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:mapper/*.xml" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.simon.mapper" />
</bean>
</beans>
applicationContext-service.xml
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"
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">
<context:component-scan base-package="com.simon.service" />
</beans>
applicationContext-shiro.xml
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 构建realm-->
<bean id="realm" class="com.simon.realm.ShiroRealm" />
<!-- 构建securityManager-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="realm"/>
</bean>
<!-- 构建ShiroFilter实例-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.html" />
<property name="filterChainDefinitionMap">
<map>
<entry key="/login.html" value="anon" />
<entry key="/user/**" value="anon" />
<entry key="/**" value="authc" />
</map>
</property>
</bean>
</beans>
db.properties
java
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql:///shiro-web
jdbc.username=root
jdbc.password=root
springmvc.xml
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: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/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.simon.controller" />
<mvc:default-servlet-handler />
</beans>
表结构
sql
/*
Navicat Premium Data Transfer
Source Server : shiro
Source Server Type : MySQL
Source Server Version : 80027
Source Host : localhost:3306
Source Schema : shiro-web
Target Server Type : MySQL
Target Server Version : 80027
File Encoding : 65001
Date: 23/09/2025 18:01:14
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for role_perm
-- ----------------------------
DROP TABLE IF EXISTS `role_perm`;
CREATE TABLE `role_perm` (
`rid` int(0) NULL DEFAULT NULL,
`pid` int(0) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of role_perm
-- ----------------------------
INSERT INTO `role_perm` VALUES (1, 2);
INSERT INTO `role_perm` VALUES (1, 2);
INSERT INTO `role_perm` VALUES (1, 3);
INSERT INTO `role_perm` VALUES (1, 4);
INSERT INTO `role_perm` VALUES (2, 4);
INSERT INTO `role_perm` VALUES (2, 4);
INSERT INTO `role_perm` VALUES (2, 4);
INSERT INTO `role_perm` VALUES (3, 4);
-- ----------------------------
-- Table structure for tb_permission
-- ----------------------------
DROP TABLE IF EXISTS `tb_permission`;
CREATE TABLE `tb_permission` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`perm_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tb_permission
-- ----------------------------
INSERT INTO `tb_permission` VALUES (1, 'user:add');
INSERT INTO `tb_permission` VALUES (2, 'user:update');
INSERT INTO `tb_permission` VALUES (3, 'user:delete');
INSERT INTO `tb_permission` VALUES (4, 'user:select');
-- ----------------------------
-- Table structure for tb_role
-- ----------------------------
DROP TABLE IF EXISTS `tb_role`;
CREATE TABLE `tb_role` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`role_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tb_role
-- ----------------------------
INSERT INTO `tb_role` VALUES (1, '超级管理员');
INSERT INTO `tb_role` VALUES (2, '运营');
INSERT INTO `tb_role` VALUES (3, '市场');
-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`salt` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (1, 'admin', 'admin', 'admin');
INSERT INTO `tb_user` VALUES (2, 'root', 'root', 'root');
-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`uid` int(0) NULL DEFAULT NULL,
`rid` int(0) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES (1, 1);
INSERT INTO `user_role` VALUES (1, 2);
INSERT INTO `user_role` VALUES (1, 3);
INSERT INTO `user_role` VALUES (2, 2);
INSERT INTO `user_role` VALUES (2, 3);
SET FOREIGN_KEY_CHECKS = 1;
实体类
java
package com.simon.entity;
/**
*/
public class Permission {
private Integer id;
private String permName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getPermName() {
return permName;
}
public void setPermName(String permName) {
this.permName = permName;
}
}
java
package com.simon.entity;
/**
*/
public class Role {
private Integer id;
private String roleName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
}
java
package com.simon.entity;
/**
* 映射用户表
*/
public class User {
private Integer id;
private String username;
private String password;
private String salt;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
}
service
java
package com.simon.service;
import com.simon.entity.User;
public interface UserService {
User findByUsername(String username);
}
java
package com.simon.service;
import java.util.Set;
import com.simon.entity.Role;
public interface RoleService {
/**
* 根据用户id查询角色信息
* @param uid
* @return
*/
Set<Role> findRolesByUid(Integer uid);
}
java
package com.simon.service;
import java.util.Set;
import com.simon.entity.Permission;
public interface PermissionService {
/**
* 根据角色id,查询角色对应的权限
* @param roleIdSet
* @return
*/
Set<Permission> findPermsByRoleSet(Set<Integer> roleIdSet);
}
java
package com.simon.service.impl;
import com.simon.entity.User;
import com.simon.mapper.UserMapper;
import com.simon.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User findByUsername(String username) {
return userMapper.findUserByUsername(username);
}
}
java
package com.simon.service.impl;
import com.simon.entity.Role;
import com.simon.mapper.RoleMapper;
import com.simon.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Set;
@Service
public class RoleServiceImpl implements RoleService {
@Autowired
private RoleMapper roleMapper;
@Override
public Set<Role> findRolesByUid(Integer uid) {
return roleMapper.findRolesByUid(uid);
}
}
java
package com.simon.service.impl;
import com.simon.entity.Permission;
import com.simon.mapper.PermissionMapper;
import com.simon.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Set;
@Service
public class PermissionServiceImpl implements PermissionService {
@Autowired
private PermissionMapper permissionMapper;
@Override
public Set<Permission> findPermsByRoleSet(Set<Integer> roleIdSet) {
return permissionMapper.findPermsByRoleIdIn(roleIdSet);
}
}
mapper
java
package com.simon.mapper;
import com.simon.entity.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {
@Select("select * from tb_user where username = #{username}")
User findUserByUsername(@Param("username")String username);
}
java
package com.simon.mapper;
import com.simon.entity.Role;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.Set;
public interface RoleMapper {
@Select("select r.* from tb_role r, user_role ur where r.id = ur.rid and ur.uid = #{uid}")
Set<Role> findRolesByUid(@Param("uid")Integer uid);
}
java
package com.simon.mapper;
import com.simon.entity.Permission;
import org.apache.ibatis.annotations.Param;
import java.util.Set;
public interface PermissionMapper {
Set<Permission> findPermsByRoleIdIn(@Param("roleIdSet") Set<Integer> roleIdSet);
}
ShiroRealm
java
package com.simon.realm;
import com.alibaba.druid.util.StringUtils;
import com.simon.entity.Permission;
import com.simon.entity.Role;
import com.simon.entity.User;
import com.simon.service.PermissionService;
import com.simon.service.RoleService;
import com.simon.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.authc.credential.HashedCredentialsMatcher;
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 org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.Set;
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
@Autowired
private PermissionService permissionService;
{
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("MD5");
matcher.setHashIterations(1024);
this.setCredentialsMatcher(matcher);
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//1. 基于Token获取用户名
String username = (String) token.getPrincipal();
//2. 判断用户名(非空)
if(StringUtils.isEmpty(username)){
// 返回null,会默认抛出一个异常,org.apache.shiro.authc.UnknownAccountException
return null;
}
//3. 如果用户名不为null,基于用户名查询用户信息
User user = userService.findByUsername(username);
//4. 判断user对象是否为null
if(user == null){
return null;
}
//5. 声明AuthenticationInfo对象,并填充用户信息
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),"ShiroRealm!!");
// 设置盐!
info.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));
//6. 返回info
return info;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//1. 获取认证用户的信息
User user = (User) principals.getPrimaryPrincipal();
//2. 基于用户信息获取当前用户拥有的角色。
Set<Role> roleSet = roleService.findRolesByUid(user.getId());
Set<Integer> roleIdSet = new HashSet<>();
Set<String> roleNameSet = new HashSet<>();
for (Role role : roleSet) {
roleIdSet.add(role.getId());
roleNameSet.add(role.getRoleName());
}
//3. 基于用户拥有的角色查询权限信息
Set<Permission> permSet = permissionService.findPermsByRoleSet(roleIdSet);
Set<String> permNameSet = new HashSet<>();
for (Permission permission : permSet) {
permNameSet.add(permission.getPermName());
}
//4. 声明AuthorizationInfo对象作为返回值,传入角色信息和权限信息
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(roleNameSet);
info.setStringPermissions(permNameSet);
//5. 返回
return info;
}
}
controller
java
package com.simon.controller;
import com.simon.entity.User;
import com.simon.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/test")
public User test(String username){
return userService.findByUsername(username);
}
}
配置tomcat,启动服务
注意:
可以通过maven插件或者本地server的方式启动