SpringBoot与Shiro整合———Shiro简介

Shiro

Shiro介绍

一款主流的java安全框架 不依赖任何容器  
可以运行在javaSE 和java EE项目中,
主要作用对访问系统的用户进行身份认证(进行登录操作),
授权(拥有某些权限才可以进行访问某个模块),会话管理,加密操作。

Shiro 结构化 工程化 解决大型项目中的安全

Shiro 就是用来解决管理的系统化框架。

编写认证和授权规则

Anon 无需认证

Authc 必须认证

authcBasic 需要通过HTTPBasic认证

user 不一定通过认证 只要曾经被Shiro记录即可 比如 记住我

授权过滤器

Perms 必须拥有某个权限 才能访问

Role 必须拥有某个角色才能访问

Port 请求的端口必须是指定值才可以

Rest 请求必须基于Restful POST、PUT、GET、DELETE

Ssl 必须是安全的url请求 协议是https

Shiro核心组件

用户、角色、权限

会给角色赋予权限 给用户赋予角色

SpringBoot与Shiro整合———Shiro简介_第1张图片

1. UsernamePasswordToken Shiro 用来封装用户登录信息 使用用户的登录信息来创建令牌Token。
2. SecurityManager Shiro的核心部分 负责安全认证和授权。
3. Suject Shiro的一个抽象概念 包含了用户信息
4. Realm 开发者自定义模块 根据项目的需求 验证和授权的逻辑 全部卸载Realm中
5. Authenticationinfo 用户的角色信息集合 认证时使用
6. Authorzationinfo 角色的权限信息 授权时使用
7. DefaultWebSecurityManager 安全管理器
开发者自定义的Realm、需要注入到DefaultWebSecurityManager 进行管理才可以生效
8. ShiroFilterFactoryBean 过滤器工厂 Shiro的基本运行机制是开发者定制规则 Shiro去执行,具体的执行操作就是由ShiroFilterFactoryBean创建的一个个Filter 对象来完成的

  • Shiro整体的运行流程

SpringBoot与Shiro整合———Shiro简介_第2张图片

自定义Shrio过滤器
对这个url进行拦截,需要先进行认证 根据需求判断对应的角色和权限

SpringBoot整合Shiro

对应的数据库展示
SpringBoot与Shiro整合———Shiro简介_第3张图片

项目结构

SpringBoot与Shiro整合———Shiro简介_第4张图片

pom.xml

<?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.6.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>SpringBoot_Shiro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringBoot_Shiro</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <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>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.5.3</version>
        </dependency>

        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

ShiroConfig 配置类


//  配置类

@Configuration
public class ShiroConfig {


    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean  factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);

        // 权限设置
        Map<String,String> map = new HashMap<>();
        map.put("/main","authc");
        map.put("/manage","perms[manage]");
        map.put("/administrator","roles[administrator]");
        //  通过这个map进行设置相对应的过滤器
        factoryBean.setFilterChainDefinitionMap(map);
        //  设置登录页面  发送这个请求 被视图解析器 捕获  跳转到login.html
        factoryBean.setLoginUrl("/login");
        //  设置未授权页面
        factoryBean.setUnauthorizedUrl("/unauth");
        return factoryBean;
    }



    @Bean
    public DefaultWebSecurityManager securityManager(@Qualifier("accountRealm") AccountRealm accountRealm){
          DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
          manager.setRealm(accountRealm);
          return manager;
    }



    @Bean
    public AccountRealm accountRealm(){
        return  new AccountRealm();
    }



    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }

}

AccountController 控制类


@Controller
//@RestController
public class AccountController {

    @GetMapping("/{url}")
    public String redirect(@PathVariable("url") String url){
        return url;
    }


    @PostMapping("/login")
    public String login(String username , String password, Model model){
        //  subject一个抽象概念  包含了用户信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        try {
            subject.login(token);
            return "index";
        }catch (UnknownAccountException e){
            e.printStackTrace();
            model.addAttribute("msg","用户名错误");
            return "login";
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            model.addAttribute("msg","密码错误");
            return "login";
        }
    }

    @GetMapping("/unauth")
    @ResponseBody
    public String unauth(){
        return "未授权,无法访问";

    }
}

AccountRealm realm自定义类

//自定义Realm
public class AccountRealm extends AuthorizingRealm {



    @Autowired
    private AccountService accountService;
//     用户的角色权限信息集合  授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取当前用户的信息
        Subject subject = SecurityUtils.getSubject();
        Account account = (Account) subject.getPrincipal();

        //  设置角色
        Set<String>  roles = new HashSet<>();
        roles.add(account.getRole());
        SimpleAuthorizationInfo  info = new SimpleAuthorizationInfo(roles);

        //  设置权限
        info.addStringPermission(account.getPerms());

        return info;
    }


//     用户的角色信息集合  登录
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

        Account account =  accountService.finByUseranme(token.getUsername());
        if(account != null){
            return  new SimpleAuthenticationInfo(account,account.getPassword(),getName());
        }
        return null;
    }
}

SpringBoot与Shiro整合———Shiro简介_第5张图片

  • 客户端拿到密码和用户名自动封装到token中 然后根据对应的用户名 进行查询 如果结果为null 表示没有该用户
    跳出对密码的验证 Shiro会抛出 一个账户不存在

  • 如果用户名存在 则开始验证密码 其中包括正确的密码 account.getPassword() 在和token中的密码 进行对比
    在SimpleAuthenticationInfo这个方法总进行对比

客户端拿到密码和用户名自动封装到token中 然后根据对应的用户名 进行查询 如果结果为null 表示没有该用户 跳出对密码的验证 Shiro会抛出 一个账户不存在

如果用户名存在 则开始验证密码 其中包括正确的密码 account.getPassword() 在和token中的密码 进行对比 在SimpleAuthenticationInfo这个方法总进行对比

SpringBoot与Shiro整合———Shiro简介_第6张图片

SpringBoot与Shiro整合———Shiro简介_第7张图片

运行结果展示

罗三用户登录效果
SpringBoot与Shiro整合———Shiro简介_第8张图片

王三用户登录效果

SpringBoot与Shiro整合———Shiro简介_第9张图片

你可能感兴趣的:(后端,java)