前言:
开发工具:IDEA
开发JDK版本:1.8
Maven版本:3.3+
①、maven的主配置settting.xml 文件中,需要配置 jdk 的版本,修改本地仓库默认位置、使用 阿里的远程仓库
②、在IDEA中配置 maven插件
目录
一、创建 SpringBoot项目,项目名为:ruoyi
二、引入依赖
三、登录页面
四、引入验证码
五、引入Shiro框架
六、在shiro中添加 验证码过滤器,完成首页验证码的显示
七、优化 ShiroConfig 权限配置类
①、使用 Spring Initializr 初始化器创建一个 SpringBoot 项目,项目名为 ruoyi、选中 web模块
②、创建项目包结构:
com.ruoyi.common.constant
com.ruoyi.common.core
com.ruoyi.common.enums
com.ruoyi.common.exception
com.ruoyi.common.utils
com.ruoyi.framework.config
com.ruoyi.framework.shiro
com.ruoyi.framework.util
com.ruoyi.framework.web.service
com.ruoyi.system.domain
com.ruoyi.system.mapper
com.ruoyi.system.service
com.ruoyi.system.service.impl
com.ruoyi.web.controller.system
③、在resources 目录下创建如下文件夹
// 存放 mapper.xml 文件
resources/mapper/system
// 存放 mybatis 配置相关文件
resources/mybatis
// 存放静态资源文件
resources/static
// 存放 模块相关的 html 文件
resources/templates/system
本着用什么依赖,引入什么依赖的原则,先引入2个基本依赖
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
补充:引入 thymeleaf 依赖后,当 Controller 层返回的结果是字符串时,SpringBoot才会使用 themeleaf模板引擎解析字符串,返回相应的页面。例如 返回的是 “/system/user/user" 字符串, SpringBoot中对应的页面是:templates/system/user/user.html
若依项目用到static 文件夹中静态资源,见百度网盘:https://pan.baidu.com/s/1sEe5FzYwEaFza0Mh1T-h4Q 提取码:yl2p
①、先从百度网盘中下载staitc.zip,将里面的内容拷贝到 static 文件夹中
②、编写 login.html 登录页面,即创建文件 templates / login.html, 内容如下:
登录若依系统
补充:
1)、引入 xmlns:th="http://www.thymeleaf.org" 命名空间,这样在 IDEA中 使用 th: 就有提示。
2)、@{请求路径}, 若路径以 / 开头,那么请求地址为 http://localhost:端口号/ 请求路径,
3)、如果请求地址是静态资源,那么SpringBoot 会去默认的4个地方找:
classpath:/static 、 classpath:/public、 classpath:/resources、classpath:/META-INF/resources
例如:请求 http://localhost:8080/1.jpg ,那么SpringBoot 默认会去上面这4个地方查找 1.jpg 文件
当然,也可以在 application.yml 中新增静态资源 :spring.resources.static-locations = “新的静态资源路径”
③、编写Controller ,处理 /login 请求
package com.ruoyi.web.controller.system;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author liangcy
* @create 2019/10/8 - 18:36
*/
@Controller
public class SysLoginController {
@GetMapping("/login")
public String login() {
return "/login";
}
}
④、启动 项目,访问登录页面 :http://localhost:8080/login
验证码的依赖、配置、以及Controller 层处理验证码请求,详情见上一篇 SpringBoot 验证码:https://blog.csdn.net/u010559460/article/details/102820228
实现效果:
此步骤 引入shiro 框架,主要是做一些拦截功能,拦截一些请求,放行一些请求。
例如:拦截验证码请求,放行访问登录页面请求
后面还会 完成 使用 shiro登录认证,授权,登出,记住我、以及与缓存结合使用的功能。
①、引入shiro 依赖
org.apache.shiro
shiro-core
1.4.1
org.apache.shiro
shiro-spring
1.4.1
②、编写shiro 配置类
shiro 配置类为 SpringBoot容器中注入 3 个 bean
Ⅰ、自定义Realm :继承 AuthorizingRealm 类, 重写 doGetAuthorizationInfo(授权)、doGetAuthenticationInfo(登录认证)两个方法
Ⅱ、SecurityManager 安全管理器:将自定义Realm注入到 安全管理器中,此外还可以注入 记住我、缓存管理器、session管理器(这3个功能后面再弄)
Ⅲ、ShiroFilterFactoryBean Shiro过滤器配置:将安全管理器注入进来,可以配置登录页面,未授权页面、过滤链、过滤器
步骤1、新建 自定义Realm (UserRealm.java),内容如下:
package com.ruoyi.framework.shiro.realm;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
*
* @author liangcy
* @create 2019/10/9 - 14:20
*/
@Slf4j
public class UserRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("授权代码....");
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("登录认证代码。。。。");
return null;
}
}
补充:这里先完成拦截某些请求,放行某些请求,所以 登录认证以及授权相关的代码 暂时不写,等后面连接数据库在补上这部分内容。
步骤2、新建 ShiroConfig 配置类,为容器注入bean
package com.ruoyi.framework.config;
import com.ruoyi.framework.shiro.realm.UserRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 权限配置类
*
* @author liangcy
* @create 2019/10/8 - 22:38
*/
@Configuration
public class ShiroConfig {
@Bean
public UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
return userRealm;
}
@Bean
public SecurityManager securityManager(UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/login");
// 权限认证失败,则跳转到指定页面
shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
// Shiro连接约束配置,即过滤链的定义
LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>();
// 对静态资源设置匿名访问
filterChainDefinitionMap.put("/favicon.ico**", "anon");
filterChainDefinitionMap.put("/ruoyi.png**", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/docs/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/ajax/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/ruoyi/**", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
//filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
// 不需要拦截的访问
filterChainDefinitionMap.put("/login", "anon");
Map filters = new LinkedHashMap();
shiroFilterFactoryBean.setFilters(filters);
// 所有请求需要认证
filterChainDefinitionMap.put("/**", "user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
}
③、启动项目,访问 http://localhost:8080/captcha/captchaImage?type=char
访问过程: 发起请求 -》 shiro 拦截请求 -》发现请求路径是需要登录认证后才能访问的(即请求路径是 非anon的)-》跳转到登录页面,因此在登录页面以及登录页面所需要的静态资源 在shiro中都需要放行,否则连登录页面也是无法访问。
让我们把视角拉回到 login.html 页面和 login.js 文件,有关与验证码部分:
点击更换验证码的 js代码:
补充:需要注意到的是 上面的 captchaType 值,应该是从request 域中获取到的值,紧接着会讲到,先把request 设置的 captchaType 的地方截图出来
1)编写 验证码 过滤器类 CaptchaValidateFilter
重写 onPreHandle、isAccessAllowed、onAccessDenied 三个方法
需要注意的是 isAccessAllowed 方法默认先返回 true,否则每次请求都没法通过,从而导致请求无法进入到Controller层。
package com.ruoyi.framework.shiro.web.filter.captcha;
import com.google.code.kaptcha.Constants;
import com.ruoyi.common.constant.ShiroConstants;
import lombok.Data;
import org.apache.shiro.web.filter.AccessControlFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* 验证码 过滤器
* @author liangcy
* @create 2019/10/17 - 15:59
*/
@Data
public class CaptchaValidateFilter extends AccessControlFilter {
//是否开启验证码
private boolean captchaEnabled = true;
//验证码类型
private String captchaType = "math";
@Override
public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
request.setAttribute(ShiroConstants.CURRENT_ENABLED, captchaEnabled);
request.setAttribute(ShiroConstants.CURRENT_TYPE, captchaType);
return super.onPreHandle(request, response, mappedValue);
}
@Override
protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
return true;
}
@Override
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
return false;
}
}
2)在 ShiroConfig 配置类中注入 CaptchaValidateFilter 验证码过滤器对象
/**
* 自定义验证码过滤器
*/
@Bean
public CaptchaValidateFilter captchaValidateFilter() {
CaptchaValidateFilter captchaValidateFilter = new CaptchaValidateFilter();
captchaValidateFilter.setCaptchaEnabled(true);
captchaValidateFilter.setCaptchaType("char");
return captchaValidateFilter;
}
3)修改 ShiroConfig 配置类中的 shiroFilterFactoryBean 方法
4)重启项目,访问登录页面:http://localhost:8080/login
将 ShiroConfig 类中有些地方用到的字符串提取出来,做成使用 applicaiton.yml 中可以修改的变量
需要修改的地方有:
①、登录页面地址、未授权地址
步骤1、在 ShiroConfig 配置类中添加 4个属性
//登录地址
@Value("${shiro.user.loginUrl}")
private String loginUrl;
//未授权
@Value("${shiro.user.unauthorizedUrl}")
private String unauthorizedUrl;
//验证码开关
@Value("${shiro.user.captchaEnabled}")
private boolean captchaEnabled;
//验证码类型
@Value("${shiro.user.captchaType}")
private String captchaType;
步骤2、在application.yml 文件中设置这些值
# Shiro
shiro:
user:
# 登录地址
loginUrl: /login
# 权限认证失败地址
unauthorizedUrl: /unauth
# 验证码开关
captchaEnabled: true
# 验证码类型 math 数字计算 char 字符
captchaType: math
步骤3、替换 ShiroConfig 类中的常量
步骤4、 通过修改 application.yml 中的值控制是否生成验证码,以及生成字符验证码还是数字运算验证码