Shiro安全框架
一、与SpringBoot整合
①:框架整合
1. 创建SpringBoot项目
环境:
- jdk: 1.8
- SpringBoot: 2.5.14
2. 整合MyBatis根据实体类生成表
可查看文章:
按照以上笔记配置后在补充一下代码
- 依赖MyBatisPlus依赖
<!--mybatis-plus-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version>
</dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.9.0</version>
</dependency>
- 配置文件
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-locations: classpath:mapper/*.xml
spring:datasource:url: jdbc:mysql://您的IP地址:3306/shirodb?characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: www.Cokedriver-class-name: com.mysql.cj.jdbc.Driverjackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8servlet:multipart:max-file-size: 20MBmax-request-size: 20MB
shiro:loginUrl: /myController/loginregisterUrl: /myController/register
- 注意以下位置改成自己的路径
- 启动类
@SpringBootApplication
@MapperScan("com.it.shiro_springboot.mapper")
public class Application {public static void main (String[] args) {SpringApplication.run(Application.class, args);}}
②:登录认证实现
1.创建实体
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Integer id;private String name;private String pwd;private Integer rid;
}
2.创建mapper
@Mapper
public interface UserMapper extends BaseMapper<User> {@Select("select * from user where name = #{name}")User getUserInfoByName(String name);@Insert("insert into user(name, pwd) values(#{name},#{pwd}) ")int userRegister(@Param("name") String name, @Param("pwd") String pwd);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table (name = "user", comment = "用户表") //设置表名 注释
public class User implements Serializable {private static final long serialVersionUID = 9435278593475930L;@IsAutoIncrement //自增@IsKey //主键@Column (comment = "用户ID")//字段注释private Integer id;/*** 姓名*/@Column(name = "name", comment = "用户名", length = 100)private String name;/*** 密码*/@Column(name = "pwd", comment = "密码", length = 100)private String pwd;/*** 角色编号*/@Column(name = "rid", comment = "角色编号", length = 100)private Integer rid;
}
3.创建 service
1.创建接口
public interface UserService {// 用户登录User getUserInfoByName (String name); // 用户注册int userRegister(String name, String pwd);
}
2.创建实现类
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic User getUserInfoByName (String name) {User user = userMapper.getUserInfoByName(name);return user;}@Overridepublic int userRegister (String name, String pwd) {// md5加密SimpleHash simpleHash = new SimpleHash("MD5", pwd, "salt", 3);return userMapper.userRegister(name, simpleHash.toHex());}}
4.自定义realm
@Component
public class MyRealm extends AuthorizingRealm {@Autowiredprivate UserService userService;// 自定义授权方法@Overrideprotected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principalCollection) {return null;}// 自定义登录认证方法@Overrideprotected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken token) throws AuthenticationException {// 1.获取用户身份信息String name = token.getPrincipal().toString();// 2. 调用业务层获取用户信息(数据库中)User user = userService.getUserInfoByName(name);// 判断并将数据完成封装if (!ObjectUtils.isEmpty(user)) {SimpleAuthenticationInfo authInfo = new SimpleAuthenticationInfo(token.getPrincipal(),user.getPwd(),ByteSource.Util.bytes("salt"),token.getPrincipal().toString());return authInfo;}return null;}
}
5.编写配置类
@Configuration
public class ShiroConfig {@Autowiredprivate MyRealm myRealm;@Value("${shiro.loginUrl}")private String loginUrl;@Value("${shiro.registerUrl}")private String registerUrl;// SecurityManager@Beanpublic DefaultWebSecurityManager defaultWebSecurityManager(){// 1.创建 defaultWebSecurityManager 对象DefaultWebSecurityManager manager = new DefaultWebSecurityManager();// 2. 创建加密对象,并设置相关属性HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();// 3.采用 md5 加密matcher.setHashAlgorithmName("md5");// 4.迭代加密次数matcher.setHashIterations(3);// 5. 将加密对象存储到 myRealm 中myRealm.setCredentialsMatcher(matcher);// 6. 将 myRealm 存入 defaultWebSecurityManager 对象manager.setRealm(myRealm);// 7. 返回return manager;}// 配置 Shiro 内置过滤器拦截范围@Beanpublic DefaultShiroFilterChainDefinition shiroFilterChainDefinition(){DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();// 设置不认证可以访问的资源definition.addPathDefinition(loginUrl, "anon");definition.addPathDefinition(registerUrl, "anon");definition.addPathDefinition("/login", "anon");// 设置需要进行登录认证的拦截范围definition.addPathDefinition("/**","authc");return definition;}
}
6.实现controller
@Controller
@Slf4j
@RequestMapping("myController")
public class MyController {@Autowiredprivate UserService userService;@GetMapping("login")@ResponseBodypublic String userLogin(String name, String pwd){// 1 获取 Subject 对象Subject subject = SecurityUtils.getSubject();// 2 封装请求数据到 token 对象中UsernamePasswordToken token = new UsernamePasswordToken(name, pwd);//3 调用 login 方法进行登录认证try {subject.login(token);return "登录成功!";}catch (AuthenticationException e){e.printStackTrace();log.info("登录失败");return "登录失败!";}}@GetMapping("register")@ResponseBodypublic String register(String name, String pwd){int i = userService.userRegister(name, pwd);if (i > 0){return "注册成功!";}else {return "注册失败!";}}
}
7.测试
1.启动程序前数据库中并没有表
2.启动程序(表即可创建成功)
3.注册用户
4.登录
③:多个 realm 的认证策略设置
④:remember me 功能
⑤:用户登录认证后登出
⑥:授权、角色认证
⑤:实现缓存
⑥:会话管理
Shiro安全框架
一、与SpringBoot整合
①:框架整合
1. 创建SpringBoot项目
环境:
- jdk: 1.8
- SpringBoot: 2.5.14
2. 整合MyBatis根据实体类生成表
可查看文章:
按照以上笔记配置后在补充一下代码
- 依赖MyBatisPlus依赖
<!--mybatis-plus-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version>
</dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.9.0</version>
</dependency>
- 配置文件
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-locations: classpath:mapper/*.xml
spring:datasource:url: jdbc:mysql://您的IP地址:3306/shirodb?characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: www.Cokedriver-class-name: com.mysql.cj.jdbc.Driverjackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8servlet:multipart:max-file-size: 20MBmax-request-size: 20MB
shiro:loginUrl: /myController/loginregisterUrl: /myController/register
- 注意以下位置改成自己的路径
- 启动类
@SpringBootApplication
@MapperScan("com.it.shiro_springboot.mapper")
public class Application {public static void main (String[] args) {SpringApplication.run(Application.class, args);}}
②:登录认证实现
1.创建实体
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Integer id;private String name;private String pwd;private Integer rid;
}
2.创建mapper
@Mapper
public interface UserMapper extends BaseMapper<User> {@Select("select * from user where name = #{name}")User getUserInfoByName(String name);@Insert("insert into user(name, pwd) values(#{name},#{pwd}) ")int userRegister(@Param("name") String name, @Param("pwd") String pwd);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table (name = "user", comment = "用户表") //设置表名 注释
public class User implements Serializable {private static final long serialVersionUID = 9435278593475930L;@IsAutoIncrement //自增@IsKey //主键@Column (comment = "用户ID")//字段注释private Integer id;/*** 姓名*/@Column(name = "name", comment = "用户名", length = 100)private String name;/*** 密码*/@Column(name = "pwd", comment = "密码", length = 100)private String pwd;/*** 角色编号*/@Column(name = "rid", comment = "角色编号", length = 100)private Integer rid;
}
3.创建 service
1.创建接口
public interface UserService {// 用户登录User getUserInfoByName (String name); // 用户注册int userRegister(String name, String pwd);
}
2.创建实现类
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic User getUserInfoByName (String name) {User user = userMapper.getUserInfoByName(name);return user;}@Overridepublic int userRegister (String name, String pwd) {// md5加密SimpleHash simpleHash = new SimpleHash("MD5", pwd, "salt", 3);return userMapper.userRegister(name, simpleHash.toHex());}}
4.自定义realm
@Component
public class MyRealm extends AuthorizingRealm {@Autowiredprivate UserService userService;// 自定义授权方法@Overrideprotected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principalCollection) {return null;}// 自定义登录认证方法@Overrideprotected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken token) throws AuthenticationException {// 1.获取用户身份信息String name = token.getPrincipal().toString();// 2. 调用业务层获取用户信息(数据库中)User user = userService.getUserInfoByName(name);// 判断并将数据完成封装if (!ObjectUtils.isEmpty(user)) {SimpleAuthenticationInfo authInfo = new SimpleAuthenticationInfo(token.getPrincipal(),user.getPwd(),ByteSource.Util.bytes("salt"),token.getPrincipal().toString());return authInfo;}return null;}
}
5.编写配置类
@Configuration
public class ShiroConfig {@Autowiredprivate MyRealm myRealm;@Value("${shiro.loginUrl}")private String loginUrl;@Value("${shiro.registerUrl}")private String registerUrl;// SecurityManager@Beanpublic DefaultWebSecurityManager defaultWebSecurityManager(){// 1.创建 defaultWebSecurityManager 对象DefaultWebSecurityManager manager = new DefaultWebSecurityManager();// 2. 创建加密对象,并设置相关属性HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();// 3.采用 md5 加密matcher.setHashAlgorithmName("md5");// 4.迭代加密次数matcher.setHashIterations(3);// 5. 将加密对象存储到 myRealm 中myRealm.setCredentialsMatcher(matcher);// 6. 将 myRealm 存入 defaultWebSecurityManager 对象manager.setRealm(myRealm);// 7. 返回return manager;}// 配置 Shiro 内置过滤器拦截范围@Beanpublic DefaultShiroFilterChainDefinition shiroFilterChainDefinition(){DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();// 设置不认证可以访问的资源definition.addPathDefinition(loginUrl, "anon");definition.addPathDefinition(registerUrl, "anon");definition.addPathDefinition("/login", "anon");// 设置需要进行登录认证的拦截范围definition.addPathDefinition("/**","authc");return definition;}
}
6.实现controller
@Controller
@Slf4j
@RequestMapping("myController")
public class MyController {@Autowiredprivate UserService userService;@GetMapping("login")@ResponseBodypublic String userLogin(String name, String pwd){// 1 获取 Subject 对象Subject subject = SecurityUtils.getSubject();// 2 封装请求数据到 token 对象中UsernamePasswordToken token = new UsernamePasswordToken(name, pwd);//3 调用 login 方法进行登录认证try {subject.login(token);return "登录成功!";}catch (AuthenticationException e){e.printStackTrace();log.info("登录失败");return "登录失败!";}}@GetMapping("register")@ResponseBodypublic String register(String name, String pwd){int i = userService.userRegister(name, pwd);if (i > 0){return "注册成功!";}else {return "注册失败!";}}
}
7.测试
1.启动程序前数据库中并没有表
2.启动程序(表即可创建成功)
3.注册用户
4.登录