三、SpringBoot整合Shiro思路

首先从客户端发来的所有请求都经过Shiro过滤器,如果用户没有认证的都打回去进行认证,认证成功的,再判断是否具有访问某类资源(公有资源,私有资源)的权限,如果没有权限,访问失败;如果有权限访问成功。注意:客户端传来的token要和realm中的认证信息进行相同规则的比较(加密算法要一致)。

shiro常见的过滤器

Filter Name Class 功能
anon org.apache.shiro.web.filter.authc.AnonymousFilter 指定url可以匿名访问
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter 指定url需要form表单登录,默认会请求username、password。rememberMe等参数并尝试登录,如果登录不了就会跳转到loginUrl配置的路径。我们也可以用这个过滤器设置默认的路径。
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter 指定url需要http认证
authcBearer org.apache.shiro.web.filter.authc.BearerHttpAuthenticationFilter 需要用户认证成功才能访资源否则就通过http请求登录
logout org.apache.shiro.web.filter.authc.LogoutFilter 登出过滤器,配置URL实现退出登录的功能。
noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter 禁止创建会话
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter 指定权限才能访问
port org.apache.shiro.web.filter.authz.PortFilter 指定端口才能访问
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter 将HTPP请求方法转化成权限字符串
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter 指定角色才能访问
ssl org.apache.shiro.web.filter.authz.SslFilter 需要https请求才能访问
user org.apache.shiro.web.filter.authc.UserFilter 需要已登录或者记住我的用户才能访问

SpringBoot整合Shiro实现认证

没有加密版

1、首先创建SpringBoot应用,勾选web模块

2、然后导入SpringBoot与shiro整合的依赖

<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入SpringBoot与shiro整合的依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.5.3</version>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

3、创建Shiro的配置类。

@Configuration
public class ShiroConfig { @Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
// 创建ShiroFilterFactoryBean
ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
filterFactoryBean.setSecurityManager(defaultWebSecurityManager); //配置受限资源,index是受限资源,authc
Map<String, String> map = new HashMap<String, String>();
// /**代表匹配所有url
map.put("/**", "authc");
// /user/login 是可以匿名访问的也就是公有资源
map.put("/user/login", "anon");
filterFactoryBean.setFilterChainDefinitionMap(map); // 设置默认认证路径 其实shiro默认的认证路径就是login.jsp
filterFactoryBean.setLoginUrl("/login.jsp"); return filterFactoryBean; } @Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
} @Bean
public Realm getRealm() {
CustomRelam customRelam = new CustomRelam();
return customRelam;
} }

4、创建自定义realm。

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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection; public class CustomRelam extends AuthorizingRealm {
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
} //认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String principal = (String) authenticationToken.getPrincipal();
// 实际开发中 先确认传来的token用户名是否存在,如果存在,然后根据有户名查询密码返回,进而判断密码是否正确 // 这里假设从数据库中查到的用户名是 xiaozhang
String username = "xiaozhang";
if (username.equals(principal)) {
// 密码还没加密,下一步会加盐并加密
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,
"123", this.getName());
// 用户名和面都判断完成后可以返回
return simpleAuthenticationInfo;
} return null;
}
}

5、编写controller,处理登录和退出的请求

package club.qy.datao.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
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; /**
* @author 胡
*/
@Controller
@RequestMapping("/user")
public class UserController {
// 退出操作
@RequestMapping("/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "redirect:/login.jsp";
}
// 登录请求
@PostMapping("/login")
public String login(String username, String password) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken passwordToken = new UsernamePasswordToken(username, password);
try {
subject.login(passwordToken);
return "redirect:/index.jsp";
} catch (UnknownAccountException e) {
System.out.println("用户名错误" + e.getMessage()); } catch (IncorrectCredentialsException e) {
System.out.println("密码错误" + e.getMessage());
} return "redirect:/login.jsp"; } }

下面开始连接数据库MySQLMD5+salt验证登录的认证

数据库表的创建

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(40) DEFAULT NULL,
`password` varchar(40) DEFAULT NULL,
`salt` varchar(40) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;

注册页面

<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" %>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1 class="">注册页</h1>
<form action="${pageContext.request.contextPath}/user/register" method="post">
用户名:<input type="text" name="username"><br/>
密码: <input type="password" name="password"><br/>
<input type="submit" value="注册">
</form> </body>
</html>

导入依赖

<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入SpringBoot与shiro整合的依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.5.3</version>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency> <!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.8</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.19</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

配置文件

server.port=8081
server.servlet.context-path=/shiro
spring.application.name=shiro spring.mvc.view.suffix=.jsp
spring.mvc.view.prefix=/ spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3309/shiro?characterEncoding=UTF-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456 mybatis.type-aliases-package=club.qy.datao.entity
mybatis.mapper-locations=classpath:mapper/*.xml

创建实体类

@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class User { private String username;
private String password;
private Integer id;
private String salt; }

创建UserDao

@Repository
@Mapper
public interface UserDao {
void saveUser(User user);
}

UserDaoMapper.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="club.qy.datao.dao.UserDao">
<insert id="saveUser" parameterType="club.qy.datao.entity.User" useGeneratedKeys="true" keyProperty="id">
insert into t_user values (#{id},#{username},#{password},#{salt})
</insert>
</mapper>

service实现

@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao; @Override
public void register(User user) { //1。生成随机盐
String saltString = SaltUtil.getSaltString(9);
//2、给用户设置盐
user.setSalt(saltString);
//3、明文密码进行散列算法1024次,并加盐
Md5Hash md5Hash = new Md5Hash(user.getPassword(), saltString, 1024);
//4、将转成16进制的密码封装到user对象中
user.setPassword(md5Hash.toHex());
//5、插入数据库
userDao.saveUser(user); }
}

SaltUtil工具类

public class SaltUtil {

    public static String getSaltString(int n){

        StringBuilder stringBuilder = new StringBuilder();
char[] array = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ!@~><?abcdefghijklmnopqrstuvwxyz".toCharArray();
for (int i = 0; i < n; i++) {
char ch = array[new Random().nextInt(array.length)];
stringBuilder.append(ch);
}
return stringBuilder.toString();
} }

ShiroConfig类

@Configuration
public class ShiroConfig { @Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
// 创建ShiroFilterFactoryBean
ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
filterFactoryBean.setSecurityManager(defaultWebSecurityManager); //配置受限资源,index是受限资源,authc
Map<String, String> map = new HashMap<String, String>();
// /**代表匹配所有url
map.put("/**", "authc");
// /user/login 是可以匿名访问的也就是公有资源
map.put("/user/**", "anon");
map.put("/register.jsp", "anon");
filterFactoryBean.setFilterChainDefinitionMap(map); // 设置默认认证路径 其实shiro默认的认证路径就是login.jsp
filterFactoryBean.setLoginUrl("/login.jsp");
return filterFactoryBean;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
} @Bean
public Realm getRealm() {
CustomRelam customRelam = new CustomRelam();
return customRelam;
}
}

SpringBoot整合Shiro完成认证的更多相关文章

  1. SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理|前后端分离(下)----筑基后期

    写在前面 在上一篇文章<SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理(上)----筑基中期>当中,我们初步实现了SpringBoot整合Shiro ...

  2. SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理(上)----筑基中期

    写在前面 通过前几篇文章的学习,我们从大体上了解了shiro关于认证和授权方面的应用.在接下来的文章当中,我将通过一个demo,带领大家搭建一个SpringBoot整合Shiro的一个项目开发脚手架, ...

  3. SpringBoot 整合 Shiro 密码登录与邮件验证码登录(多 Realm 认证)

    导入依赖(pom.xml)  <!--整合Shiro安全框架--> <dependency> <groupId>org.apache.shiro</group ...

  4. SpringBoot整合Shiro 四:认证+授权

    搭建环境见: SpringBoot整合Shiro 一:搭建环境 shiro配置类见: SpringBoot整合Shiro 二:Shiro配置类 shiro整合Mybatis见:SpringBoot整合 ...

  5. 补习系列(6)- springboot 整合 shiro 一指禅

    目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...

  6. spring-boot(八) springboot整合shiro-登录认证和权限管理

    学习文章:springboot(十四):springboot整合shiro-登录认证和权限管理 Apache Shiro What is Apache Shiro? Apache Shiro是一个功能 ...

  7. SpringBoot系列十二:SpringBoot整合 Shiro

    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot 整合 Shiro 2.具体内容 Shiro 是现在最为流行的权限认证开发框架,与它起名的只有最初 ...

  8. SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建

    SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建 技术栈 : SpringBoot + shiro + jpa + freemark ,因为篇幅原因,这里只 ...

  9. 转:30分钟了解Springboot整合Shiro

    引自:30分钟了解Springboot整合Shiro 前言:06年7月的某日,不才创作了一篇题为<30分钟学会如何使用Shiro>的文章.不在意之间居然斩获了22万的阅读量,许多人因此加了 ...

随机推荐

  1. APIO2012 苦无 Kunai

    这题网上貌似还没有完整的题解呢,我来口胡一下~ Description \(W \times H\) 的二维坐标系,\(W, H \le 10^9\) 给 \(n (n \le 10^5)\) 个点 ...

  2. 笔记-[ZJOI2007]仓库建设

    笔记-[ZJOI2007]仓库建设 [ZJOI2007]仓库建设 \(f_i\) 到第 \(i\) 个工厂并且建设了仓库. \[\begin{split} f_i=&\min\{f_j+\su ...

  3. SpringBoot添加多数据源mysql和oracle

    项目结构 多数据源配置文件 MultiDataSourceConfig.java SqlSessionTemplate1.java SqlSessionTemplate2.java package c ...

  4. day109:MoFang:好友列表显示&添加好友页面初始化&添加好友后端接口

    目录 1.好友列表 2.添加好友-前端 3.服务端提供添加好友的后端接口 1.好友列表 1.在用户中心页面添加好友列表点击入口 html/user.html,用户中心添加好友列表点击入口,代码: &l ...

  5. Flink如何做维表关联?

    使用 RichAsyncFunction 加 CacheBuilder CacheBuilder.newBuilder() //最多存储10000条 .maximumSize(10000) //过期时 ...

  6. Hexo结合Stun静态博客搭建从入门到入土

    摘要 安装npm,安装hexo相关依赖,安装主题stun 修改hexo配置,修改stun配置,部署到github,gitee实现静态访问 给博客加上全局搜索,访问量统计 hexo博客编写模板 tips ...

  7. matplotlib的学习14-图中图

    # 导入pyplot模块 import matplotlib.pyplot as plt # 初始化figure fig = plt.figure() # 创建数据 x = [1, 2, 3, 4, ...

  8. ELK原理介绍

    本篇转载自:https://www.cnblogs.com/aresxin/p/8035137.html 为什么使用日志系统: 日志系统记录了系统运行.业务处理的方方面面,在故障排除.业务分析.数据挖 ...

  9. [EF] - 作为DAL层遇到的问题

    今天在部署一个经典三层的项目的时候,用到了EntityFramework,碰到几个问题: 在用EntityFramework将数据库导入到DAL层后,在BL层引用该DAL后,在测试项目的时候,想要查询 ...

  10. C#中的深度学习(五):在ML.NET中使用预训练模型进行硬币识别

    在本系列的最后,我们将介绍另一种方法,即利用一个预先训练好的CNN来解决我们一直在研究的硬币识别问题. 在这里,我们看一下转移学习,调整预定义的CNN,并使用Model Builder训练我们的硬币识 ...