课程链接:https://www.bilibili.com/video/BV1PE411i7CV?from=search&seid=3765473467792965977
狂神说SpringBoot01:Hello,World!
狂神说SpringBoot02:运行原理初探
狂神说SpringBoot03:yaml配置注入
狂神说SpringBoot04:JSR303数据校验及多环境切换
狂神说SpringBoot05:自动配置原理
狂神说SpringBoot06:自定义starter
狂神说SpringBoot07:整合JDBC
狂神说SpringBoot08:整合Druid
狂神说SpringBoot09:整合MyBatis
狂神说SpringBoot10:Web开发静态资源处理
狂神说SpringBoot11:Thymeleaf模板引擎
狂神说SpringBoot12:MVC自动配置原理
狂神说SpringBoot13:页面国际化
狂神说SpringBoot14:集成Swagger终极版
狂神说SpringBoot15:异步、定时、邮件任务
狂神说SpringBoot16:富文本编辑器
狂神说SpringBoot17:Dubbo和Zookeeper集成
狂神说SpringBoot18:集成SpringSecurity
//获取所有配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes);
获取候选配置:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
file : 文件路径,就是项目路径
自动装配:
SpringBoot到底帮我们配置了什么?我们能不能进行修改?能修改哪些东西?能不能扩展?
要解决的问题:
导入静态资源…
首页
jsp, 模板引擎Thymeleaf
thymeleaf依赖
装配扩展SpringMVC
增删改查
拦截器
国际化
LocaleResolver
@Bean
整合包
mybatis-spring-boot-starter
导入包
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.1version>
dependency>
配置yml文件
application.yml
# 配置spring自带的数据源
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
# 整合mybatis
mybatis:
# 别名
type-aliases-package: com.kuang.pojo
# mapper文件位置
mapper-locations: classpath:mybatis/mapper/*.xml
mybatis配置
User
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String password;
}
UserMapper接口
@Repository
@Mapper
public interface UserMapper {
public User queryUserByName(String name);
}
UserMapper.xml配置文件
<mapper namespace="com.kuang.mapper.UserMapper">
<select id="getUserList" resultType="com.kuang.pojo.User" parameterType="String">
select * from USER where name = #{name}
select>
mapper>
编写sql
service层调用dao层
UserService 接口
public interface UserService {
public User queryUserByName(String name);
}
UserServiceImpl实现类
@Service
public class UserServiceImpl implements UserService{
@Autowired
UserMapper mapper;
public User queryUserByName(String name) {
User user = mapper.queryUserByName(name);
return user;
}
}
controller调用service层
@Autowired
UserServiceImpl userService;
public void mian(String args[]){
User user = userService.queryUserByName("dog");
}
引入 Spring Security 模块
编写 Spring Security 配置类
参考官网:https://spring.io/projects/spring-security
编写基础配置类
//AOP : 拦截器
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 链式编程
@Override
//授权
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问,功能页只有对应有权限的人才能访问
//请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
//没有权限默认会到登录页面,需要开启登录的页面
http.formLogin()
.loginPage("/toLogin")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login");
http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求
// 开启注销功能
http.logout().logoutSuccessUrl("/");
//开启记住我功能
http.rememberMe().rememberMeParameter("rememberme");
}
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//在内存中定义,也可以在jdbc中去拿....
//Spring security 5.0中新增了多种加密方式,也改变了密码的格式。
//要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
//spring security 官方推荐的是使用bcrypt加密方式。
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("kuangshen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
.and()
.withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FBMQ6DqA-1594654577784)(D:\我\MyBlog\狂神说Java SpringBoot.assets\image-20200713105531285.png)]
简单实验:
导入依赖
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.5.3version>
dependency>
编写Shiro配置类
@Configuration
public class ShrioConfig {
//ShiroFilterFactoryBean : Step3
@Bean
public ShiroFilterFactoryBean getShrioFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
return bean;
}
//DefaultWebSecurityManager : Step2
@Bean("securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联userRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//创建 realm 对象, 需要自定义类:Step1
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
}
自定义UserRealm
//自定义的 UserRealm
public class UserRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
return null;
}
}
一个小Demo:
导入依赖
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.1.RELEASEversion>
<relativePath/>
parent>
<groupId>com.kuanggroupId>
<artifactId>shiro-springbootartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>shiro-springbootname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>com.github.theborakompanionigroupId>
<artifactId>thymeleaf-extras-shiroartifactId>
<version>2.0.0version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.20version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.22version>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.1version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.12version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.5.3version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion>
<groupId>org.junit.vintagegroupId>
<artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
整合MyBatis
编写Shiro配置类
@Configuration
public class ShrioConfig {
//ShiroFilterFactoryBean : Step3
@Bean
public ShiroFilterFactoryBean getShrioFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
//添加shiro的内置过滤器
/*
anno: 无需认证就可以访问
authc: 必须认证了才可以访问
user: 必须拥有 记住我 功能才能用
perms: 拥有对某个资源的权限才能访问
role: 拥有某个角色权限才能访问
*/
Map<String, String> filterMap = new LinkedHashMap<>();
//用户授权,正常情况下没有授权会跳转到授权页面
filterMap.put("/user/add","perms[user:add]");
filterMap.put("/user/update","perms[user:update]");
//拦截
//filterMap.put("/user/add","authc");
//filterMap.put("/user/update","authc");
filterMap.put("/user/*","authc");
//设置登录请求
bean.setLoginUrl("/toLogin");
//设置未授权页面
bean.setUnauthorizedUrl("/noauth");
bean.setFilterChainDefinitionMap(filterMap);
return bean;
}
//DefaultWebSecurityManager : Step2
@Bean("securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联userRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//创建 realm 对象, 需要自定义类:Step1
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
//整合 ShiroDialect:用来整合shiro thymeleaf
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
自定义UserRealm
//自定义的 UserRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserServiceImpl userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了 => doGetAuthorizationInfo");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 拿到当前登录的这个对象
Subject subject = SecurityUtils.getSubject();
// 拿到User对象
User currentUser = (User) subject.getPrincipal();
// 设置当前用户的权限
System.out.println(currentUser.getName() + "的权限为 " + currentUser.getPerms());
info.addStringPermission(currentUser.getPerms());
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了 => 认证AuthenticationToken");
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
//连接真实的数据库
User user = userService.queryUserByName(userToken.getUsername());
if(user == null){
//没有这个人
return null; //抛出异常 UnknownAccountException
}
// 登录成功 将用户信息存入session
Subject currentSubject = SecurityUtils.getSubject();
Session session = currentSubject.getSession();
session.setAttribute("loginUser",user.getName());
// 密码认证,shiro做
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
}
案例详细代码:https://gitee.com/daniel1996/shiro_springboot/tree/master/shiro-springboot