文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

springboot集成shiro详细总结

2024-04-02 19:55

关注

一、项目整体介绍:

项目整体的结构如下图所示,项目整体采用 springboot + mybatis + jsp + mysql 来完成的,下面会详细介绍下:

二、数据库脚本

先在数据库中创建 userrolepermission 这三张表,table.sql 的内容如下所示:


DROP DATABASE IF EXISTS shiro_test;
CREATE DATABASE shiro_test;
USE shiro_test;
 
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `USER_NAME` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `PASSWORD` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `ROLE_IDS` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `STATUS` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  PRIMARY KEY (`ID`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `ROLE_NAME` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `PERMISSIONS_IDS` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  PRIMARY KEY (`ID`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
 
-- ----------------------------
-- Table structure for permission
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission`  (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `PERMISSION_NAME` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  PRIMARY KEY (`ID`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
 
INSERT INTO `shiro_test`.`permission` (`ID`, `PERMISSION_NAME`) VALUES ('1', 'add');
INSERT INTO `shiro_test`.`permission` (`ID`, `PERMISSION_NAME`) VALUES ('2', 'delete');
INSERT INTO `shiro_test`.`permission` (`ID`, `PERMISSION_NAME`) VALUES ('3', 'update');
INSERT INTO `shiro_test`.`permission` (`ID`, `PERMISSION_NAME`) VALUES ('4', 'query');
 
INSERT INTO `shiro_test`.`role` (`ID`, `ROLE_NAME`, `PERMISSIONS_IDS`) VALUES ('1', 'administrator', '1,2,3,4');
INSERT INTO `shiro_test`.`role` (`ID`, `ROLE_NAME`, `PERMISSIONS_IDS`) VALUES ('2', 'normalUser', '4');

三、maven依赖:

pom.xml 的内容如下所示:


<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.RELEASE</version>
		<relativePath />
	</parent>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.6.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>1.6.0</version>
		</dependency>
		<!-- shiro -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.6.0</version>
		</dependency>
		<!-- 添加shiro web支持 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.6.0</version>
        </dependency>
		<!-- 简化model类的setter和getter -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<scope>provided</scope>
		</dependency>
		<!--热部署依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<scope>priveded</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>priveded</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

四、配置文件:

application.properties 的内容如下所示:


spring.mvc.view.prefix=/page/
spring.mvc.view.suffix=.jsp
spring.resources.static-locations=classpath:/page/
 
 
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shiro_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&nullCatalogMeansCurrent=true
spring.datasource.username=root
spring.datasource.password=Rfid123456
 
mybatis.mapper-locations=classpath*:mapper
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		// 获取登录用户名
		String name = (String)principalCollection.getPrimaryPrincipal();
		// 查询用户名称
		User user = userService.selectByUserName(name);
		// 添加角色和权限
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		List<String> roleNameList = new ArrayList<>();
		List<String> permissionNameList = new ArrayList<>();
		
		for (Role role : user.getRoles()) {
			roleNameList.add(role.getRoleName());
			for (Permission permission : role.getPermissions()) {
				permissionNameList.add(role.getRoleName()+":"+permission.getPermissionName());
			}
		}
		// 添加角色
		simpleAuthorizationInfo.addRoles(roleNameList);
		// 添加权限
		simpleAuthorizationInfo.addStringPermissions(permissionNameList);
		return simpleAuthorizationInfo;
	}
 
	
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		if(StringUtils.isEmpty(authenticationToken.getPrincipal())) {
			return null;
		}
		// 获取用户信息
		String name = authenticationToken.getPrincipal().toString();
		User user = userService.selectByUserName(name);
		// 用户是否存在
		if(user == null) {
			throw new UnknownAccountException();
		}
		// 是否激活
		if(user !=null && user.getStatus().equals("0")){
			throw new  DisabledAccountException();
		}
		// 是否锁定
		if(user!=null && user.getStatus().equals("3")){
			throw new  LockedAccountException();
		}
		// 若存在将此用户存放到登录认证info中,无需做密码比对shiro会为我们进行密码比对校验
		if(user !=null && user.getStatus().equals("1")){
			ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUserName()+ "salt");
			// 这里验证authenticationToken和simpleAuthenticationInfo的信息
			SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(),credentialsSalt, getName());
			return simpleAuthenticationInfo;
		}
		return null;
	}
}

八、配置shiro:

编写 ShiroConfig 的配置类,内容如下所示:


import java.util.HashMap;
import java.util.Map;
 
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import com.shiro.CustomRealm;
 
@Configuration
public class ShiroConfig {
 
	@Bean
	@ConditionalOnMissingBean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
		defaultAAP.setProxyTargetClass(true);
		return defaultAAP;
	}
 
	// 将自己的验证方式加入容器
	@Bean
	public CustomRealm myShiroRealm() {
		CustomRealm customRealm = new CustomRealm();
		// 告诉realm,使用credentialsMatcher加密算法类来验证密文
		customRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return customRealm;
	}
 
	// 权限管理,配置主要是Realm的管理认证
	@Bean
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(myShiroRealm());
		return securityManager;
	}
	// Filter工厂,设置对应的过滤条件和跳转条件
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		Map<String, String> map = new HashMap<>();
		//登出
		map.put("/logout", "logout");
		//对所有用户认证
		map.put("/**", "authc");
		//登录
		shiroFilterFactoryBean.setLoginUrl("/login");
		//首页
		shiroFilterFactoryBean.setSuccessUrl("/index");
		//错误页面,认证不通过跳转
		shiroFilterFactoryBean.setUnauthorizedUrl("/error");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
		return shiroFilterFactoryBean;
	}
 
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		// 散列算法:这里使用MD5算法;
		hashedCredentialsMatcher.setHashAlgorithmName("md5");
		// 散列的次数,比如散列两次,相当于 md5(md5(""));
		hashedCredentialsMatcher.setHashIterations(2);
		// storedCredentialsHexEncoded默认是true,此时用的是密码加密用的是Hex编码;false时用Base64编码
		hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
		return hashedCredentialsMatcher;
	}
}

九、登录拦截

创建 LoginController 来拦截用户的前端请求,其代码内容如下所示:


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
 
import com.entity.User;
 
import lombok.extern.slf4j.Slf4j;
 
@Controller
@Slf4j
public class LoginController {
 
	@RequestMapping("/login")
	public String login(User user) {
		if (StringUtils.isEmpty(user.getUserName()) || StringUtils.isEmpty(user.getPassword())) {
			return "error";
		}
		//用户认证信息
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
				user.getUserName(),
				user.getPassword());
		usernamePasswordToken.setRememberMe(true);
		try {
			//进行验证,这里可以捕获异常,然后返回对应信息
			subject.login(usernamePasswordToken);
		} catch (UnknownAccountException e) {
			log.error("用户名不存在!", e);
			return "error";
		} catch (AuthenticationException e) {
			log.error("账号或密码错误!", e);
			return "error";
		} catch (AuthorizationException e) {
			log.error("没有权限!", e);
			return "error";
		}
		return "shiro_index";
	}
}

十、前端展示界面:

前端用户展示的 shiro_index.jsp 内容如下所示:


<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
 
<shiro:guest>
	<h1>欢迎游客访问</h1>	
</shiro:guest>
</br>
<shiro:user>
	<h1>欢迎[<shiro:principal/>]登录</h1>
</shiro:user>
</br>
<shiro:authenticated>
	<h1>用户[<shiro:principal/>]身份已验证通过</h1>
</shiro:authenticated>
</br>
<shiro:hasAnyRoles name="administrator,normalUser">
	<h2>用户[<shiro:principal/>]拥有角色administrator或normalUser</h2>
</shiro:hasAnyRoles>
</br>
<shiro:lacksRole name="test">
   <h2> 用户[<shiro:principal/>] 没有角色test </h2>
</shiro:lacksRole>
</br>
<shiro:hasRole name="administrator">
    <h3>拥有administrator的角色才会显示这个标签</h3>
</shiro:hasRole>
</br>
<shiro:hasRole name="normalUser">
    <h3>拥有normalUser的角色才会显示这个标签</h3>
</shiro:hasRole>
</br>
<shiro:hasPermission name="normalUser:query">
	<h3>用户[<shiro:principal/>]拥有权限normalUser:query</h3>
</shiro:hasPermission>
</br>
<shiro:hasPermission name="normalUser:add">
	<h3>用户[<shiro:principal/>]拥有权限normalUser:add</h3>
</shiro:hasPermission>
</br>
<shiro:hasPermission name="administrator:add">
	<h3>用户[<shiro:principal/>]拥有权限administrator:add</h3>
</shiro:hasPermission>
</br>
<shiro:hasPermission name="administrator:delete">
	<h3>用户[<shiro:principal/>]拥有权限administrator:delete</h3>
</shiro:hasPermission>
</br>
<shiro:hasPermission name="administrator:update">
	<h3>用户[<shiro:principal/>]拥有权限administrator:update</h3>
</shiro:hasPermission>
</br>
<shiro:hasPermission name="administrator:query">
	<h3>用户[<shiro:principal/>]拥有权限administrator:query</h3>
</shiro:hasPermission>
 
</body>
</html>

error.jsp 的内容如下所示:


<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
 
<h1>账号或者密码错误!</h1>
 
</body>
</html>

十一、启动类:

启动类 App 的代码内容如下所示:


@SpringBootApplication
@MapperScan({"com.dao"}) 
public class App {
    public static void main( String[] args ){
        SpringApplication.run(App.class, args);
    }
}

十二、测试:

在浏览器输入:http://localhost:8080/login?userName=zhangsan&password=123456 展示内容如下所示:

在浏览器输入:http://localhost:8080/login?userName=zhangsan&password=123456 内容如下所示:

到此这篇关于springboot集成shiro详细总结的文章就介绍到这了,更多相关springboot集成shiro内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯