shiro安全框架从入门到精通实战!!!!
shiro面试题1、String是不是基本的数据类型?
代码语言:javascript代码运行次数:0运行复制不是,是引用类型。 地址在 栈 中存放, 值:堆;
基本类型:整形,浮点型、布尔型、字符型。;栈2、abstaract的mehtod能不能是static,同时是native, 同步的?
代码语言:javascript代码运行次数:0运行复制抽象类中可以有静态方法的。
抽象方法不能是静态的,需要被子类实现。静态方法无法被子类实现。
native:本地的。
不能???3、String和StringBuffer、StringBuilder的区别?
代码语言:javascript代码运行次数:0运行复制String是不可变的的实例对象。
StringBuffer:线程安全
StringBuilder:线程不安全的4、实现多态的机制?
代码语言:javascript代码运行次数:0运行复制1、继承关系(子类继承父类,子类实现接口)
2、父类引用 指向 子类对象;
3、子类要实现或者重写父类的方法
List list=new ArrayList();
List list=new LinkedList(); 5、数组中有没有length方法,string中有没有length方法;
代码语言:javascript代码运行次数:0运行复制数组:length属性;
String中:length()方法;学习目标1、shiro介绍
2、Springboot整合Shiro
学习内容1.shiro介绍1.1介绍shiro是一个java的 安全框架,apache的一个开源框架。简单易用。实现的功能:认证、授权、会话管理和密码加密等功能。可以用在java SE环境中,java EE环境中。1.2shrio功能特点:Authentication:认证
Authorization:授权
Session Management:session会话管理
Cryptography:密码加密
Caching:缓存
web Support:web支持
Concurrency:多线程、并发
Testing:测试
Run as: 以 某种 身份 运行
Remember Me:记住我
什么是认证:Authentication
通过用户名和密码,或者人脸识别,或者是指纹跟数据库里的数据进行匹配,如果匹配成功则代表认证通过;
什么是授权:Authorization
认证通过后,对不同的资源的访问进行控制,这就是授权的体现;
身份:用户名
凭证:密码
1.3shiro运行原理Subject:主体,抽象的身份:当前的用户,网络爬虫、第三方的程序、进程
SecurityManager:安全管理器,管理所有的subjects;委托给SecurityManager进行安全管理。门面模式:Facade;需求----》委托人————分发下去;
Realm:域,数据域。获取数据库中用户信息、权限信息。
前台用户输入用户名和密码,点击登陆后,会使用一个subject进行login;
subject使用securitymanager.login方法进行登陆;
realm:数据域,它会处理login,会拿着前台输入的用户名和密码进行与数据库里的用户名和密码进行匹配,如果匹配成功,则认证通过;
代码语言:javascript代码运行次数:0运行复制//常用过滤器
/*
* anon:不需要认证就可以访问呢
*authc:必须认证才可以访问
* user:如果实现remenberme可以直接访问
* perms:必须授权才可以访问
* role:必须得到角色才可以访问
* */2、shiro的认证步骤2.1创建springboot项目导入mybatis整合依赖;
导入MySQL驱动依赖;
导入druid依赖;
导入thymeleaf 依赖;
导入shiro和spring的整合依赖;
导入shiro和thymeleaf的整合依赖;
代码语言:javascript代码运行次数:0运行复制
2.2配置文件properties文件书写:
代码语言:javascript代码运行次数:0运行复制server.servlet.context-path=/demo
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/shiro?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=123@qwe
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.resources.static-locations=classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/templates/
mybatis.type-aliases-package=com.aaa.demo_shiro.entity
pagehelper.helperDialect = mysql
pagehelper.reasonable = true
pagehelper.supportMethodsArguments = true
pagehelper.pageSizeZero = true
pagehelper.params = countSql
logging.level.com.aaa.demo_shiro.mapper=debug
spring.thymeleaf.cache=false
spring.main.banner-mode=off2.3从之前的项目中把班级管理拿过来再把权限的五张表的数据拿过来;
在pom.xml文件中添加resources;
代码语言:javascript代码运行次数:0运行复制
2.4创建ShiroConfiguration类该类是shiro的配置文件:
在该类中需要建立四个bean:
代码语言:javascript代码运行次数:0运行复制package com.example.demo_shiro.config;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ShiroConfig {
//realm 是自己定义的,用来实现前台的用户信息和数据库的用户信息进行匹配
@Bean(name="userRealm")
public UserRealm getUserRealm(){
UserRealm userRealm = new UserRealm();
return userRealm;
}
//安全管理器securitymanager
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}
//过滤器连工厂shirofilterfactorybean
@Bean(name="shiroFilterFactoryBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
return shiroFilterFactoryBean;
}
//密码匹配器
//shiro 与thymeleaf的整合
}2.5创建测试页面、登陆、添加、修改页面然后创建对应的controller方法
2.6修改和添加页面只有认证后才可以访问在ShiroConfiguration中添加认证过滤
代码语言:javascript代码运行次数:0运行复制 @Bean(name="shiroFilterFactoryBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map
filtermap.put("/test","anon");
filtermap.put("/login","anon");
filtermap.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filtermap);
shiroFilterFactoryBean.setLoginUrl("toLogin");
return shiroFilterFactoryBean;
}2.7修改认证逻辑在controller方法的登陆方法中
代码语言:javascript代码运行次数:0运行复制三个步骤:
1.获取subject
2.封装token
3.登陆
@RequestMapping("login")
public String login(String username,String password,Model model){
System.out.println(username+"-->"+password);
//第一步获取subject
Subject subject = SecurityUtils.getSubject();
//封装token
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
//第三步login方法
try {
subject.login(token);
return "login";
} catch (UnknownAccountException e) {
model.addAttribute("msg","不存在该用户!");
return "login";
} catch (IncorrectCredentialsException e) {
model.addAttribute("msg","密码凭证错误!");
return "login";
}catch (Exception e){
model.addAttribute("msg","未知错误!");
return "login";
}
}2.8实现密码认证自己定义一个密码加密器
代码语言:javascript代码运行次数:0运行复制public class UserCredentialsMatcher {
/**
* 随机生成 salt 需要指定 它的字符串的长度
*
* @param len 字符串的长度
* @return salt
*/
public static String generateSalt(int len) {
//一个Byte占两个字节
int byteLen = len >> 1;
SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
return secureRandom.nextBytes(byteLen).toHex();
}
/**
* 获取加密后的密码,使用默认hash迭代的次数 1 次
*
* @param hashAlgorithm hash算法名称 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512、etc。
* @param password 需要加密的密码
* @param salt 盐
* @return 加密后的密码
*/
public static String encryptPassword(String hashAlgorithm, String password, String salt) {
return encryptPassword("MD5", password, salt, 2);
}
/**
* 获取加密后的密码,需要指定 hash迭代的次数
*
* @param hashAlgorithm hash算法名称 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512、etc。
* @param password 需要加密的密码
* @param salt 盐
* @param hashIterations hash迭代的次数
* @return 加密后的密码
*/
public static String encryptPassword(String hashAlgorithm, String password, String salt, int hashIterations) {
SimpleHash hash = new SimpleHash(hashAlgorithm, password, salt, hashIterations);
return hash.toString();
}
}在ShiroConfig中定义凭证匹配器
代码语言:javascript代码运行次数:0运行复制//密码匹配器
@Bean(name="hashedCredentialsMatcher")
public HashedCredentialsMatcher getHashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}给realm设置匹配器
代码语言:javascript代码运行次数:0运行复制@Bean(name="userRealm")
public UserRealm getUserRealm(@Qualifier("hashedCredentialsMatcher")HashedCredentialsMatcher hashedCredentialsMatcher){
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(hashedCredentialsMatcher);
return userRealm;
}在realm中设置如下:
代码语言:javascript代码运行次数:0运行复制SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(user.getSalt()),getName());3.shiro的授权步骤3.1 测试授权代码语言:javascript代码运行次数:0运行复制@Bean(name="shiroFilterFactoryBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map
filtermap.put("/test","anon");
filtermap.put("/login","anon");
filtermap.put("/user/add","perms[user:add]");
filtermap.put("/user/update","perms[user:update]");
filtermap.put("/classes/findall","perms[classes:findall]");
filtermap.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filtermap);
shiroFilterFactoryBean.setLoginUrl("/toLogin");
shiroFilterFactoryBean.setSuccessUrl("/hello");
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
return shiroFilterFactoryBean;
}3.2授权代码语言:javascript代码运行次数:0运行复制 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权方法");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取当前认证过的用户
Subject subject = SecurityUtils.getSubject();
SysUser user = (SysUser) subject.getPrincipal();
//查询该用户所有的授权
List
try {
ps = sysService.findPermissionListByUserId(user.getId());
} catch (Exception e) {
e.printStackTrace();
}
Set
for(SysPermission p:ps){
permissions.add(p.getPercode());
}
info.setStringPermissions(permissions);
return info;
}3.3不同的授权看到不同的资源添加依赖
代码语言:javascript代码运行次数:0运行复制
在配置类中添加bean
代码语言:javascript代码运行次数:0运行复制//配置shiroDialect,用于thymeleaf和shiro的合用
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}在test前端写代码
代码语言:javascript代码运行次数:0运行复制
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
班级管理:班级管理
用户添加:添加用户
用户修改:修改用户