首先说一下shiro最关键的东西
Subject:就是当前用户(它本意并不是这样,它指的是和软件交互的任何东西,我理解就是用户)。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm:Realm我的理解就是一个业务处理层,具体的认证、权限在这操作。

实际上我们写的时候 是反着来的(就像我们先写dao(Realm) 再写service(SecurityManager)就是这么个意思)
https://www.infoq.com/articles/apache-shiro/(shiro官网介绍)
----------------------------------------------------------------------------------------------------------------
springboot+shrio+mybatis+thymeleaf(
shiro-spring-boot-starter这个是集成的,boot2.5.2和shiro1.7.1有冲突,有些方法废弃了,所以用的1.7.0
)
依赖
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.admin</groupId>
<artifactId>shrio</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shrio</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring-boot-starter -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
写shiroConfig
bean.setUnauthorizedUrl("/noAuthentication"); 这块是定义认证失败的自定义跳转下面的1 2 3 代表我自己写的时候的顺序
Qualifier这个注解 是为了和我的1也就是realm绑定
@RequestMapping("/noAuthentication")
@ResponseBody
public String noAuthentication() {
return "未授权,请联系管理员";
}
package com.admin.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
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;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created by zhl on 2021/8/18.
*/
@Configuration
public class ShrioConfig {
//shrio filter 3
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(securityManager);
/*
* anon 所有人可以访问
* authc 必须认证
* user '记住我'访问
* perms 拥有某个资源的权限
* role 拥有某个角色权限
* */
Map<String, String> filterMap = new LinkedHashMap<>();
//这块和security 是有点不一样的 这边会依次判断 但是security是有一个没权限就会提示没权限
filterMap.put("/add", "authc");
filterMap.put("/update", "authc");
filterMap.put("/add", "perms[1]");
filterMap.put("/update", "perms[2]");
bean.setFilterChainDefinitionMap(filterMap);
//没有认证就跳到login界面
bean.setLoginUrl("/login");
//
bean.setUnauthorizedUrl("/noAuthentication");
return bean;
}
//manager 2
@Bean
public DefaultWebSecurityManager manager(@Qualifier("realm") UserRealm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联
securityManager.setRealm(realm);
return securityManager;
}
//realm 1
@Bean
public UserRealm realm() {
return new UserRealm();
}
//整合shiro与thymeleaf
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}
登录时要添加token注册
SecurityUtils.getSubject(); 官网上的直接获取当前对象new UsernamePasswordToken(username, password); 获取toke它会自动给你注册subject.login(token); //根据token注册 然后就可以在UserRealm 用这个token
@RequestMapping("/toLogin")
public String toLogin(String username, String password) {
//获取当前用户
Subject subject = SecurityUtils.getSubject();
//获取账号密码的token
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//注册
try {
subject.login(token);
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("name", username);
return "index";
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
//model.mergeAttributes("msg", "用户名不存在");
return "login";
} catch (IncorrectCredentialsException e) {
System.out.println("密码错误");
return "login";
}
}
创建UserRealm在这里面要继承AuthorizingRealm并重写认证和授权
继承这两个要返回两个对应的对象。
AuthenticationInfo 是个接口你点进去看对应的实现类 我返回的就是SimpleAuthenticationInfo(密码一般都会加salt 但是我这直接get了没加密,shiro 会自动对比)
(UsernamePasswordToken)authenticationToken; 获取controller里面的tokenloginService.getUserByName(token.getUsername()); 这个就不说了查数据库new SimpleAuthenticationInfo(user, user.getPass(),""); 我把user放进去 要在授权里查询它的权限------------------------------------------------------------------------------------------------------------
AuthorizationInfo 开始授权(UserCommen)subject.getPrincipal(); 获取认证的信息zationInfo.addStringPermission(user.getRole()); 给当前用户加上对应资源访问权限
package com.admin.config;
import com.admin.pojo.UserCommen;
import com.admin.service.LoginService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Created by zhl on 2021/8/18.
*/
//自定义realm
public class UserRealm extends AuthorizingRealm {
@Autowired
LoginService loginService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("===============>授权");
SimpleAuthorizationInfo zationInfo = new SimpleAuthorizationInfo();
//zationInfo.addStringPermission("1");
//获取当前用户对象进行权限判定
Subject subject = SecurityUtils.getSubject();
UserCommen user = (UserCommen)subject.getPrincipal();
//zationInfo.addObjectPermissions(); 多权限
zationInfo.addStringPermission(user.getRole());
return zationInfo;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("===============>认证");
//controller 注册成功后 authenticationToken全局通用
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
//取用户名密码
UserCommen user = loginService.getUserByName(token.getUsername());
if (user == null) {
//UnknownAccountException
return null;
}
return new SimpleAuthenticationInfo(user, user.getPass(),"");
}
}
我数据库结构,我为了简单就写了两张表


上面代码写了 1的权限只能有新增

2的权限只能修改


至此简单的登录、权限就搞完了(我写的比较乱 想到哪写哪,在于我自己的理解)
我自己的git地址 https://github.com/zhuhl1996/boot_SImpleShiro.git
https://github.com/apache/shiro.git 官网的地址里面有 很多例子 自己可以去下载上看看(包括怎么QuickStart)。

5286

被折叠的 条评论
为什么被折叠?



