shiro的笔记

shiro 就是一个安全管理框架 对身份验证、授权、密码和会话管理 这些操作

这张图就可以初步了解shiro

 

 Subject:主体,代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject

SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject;可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成DispatcherServlet前端控制器

Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。

 

也就是说对于我们而言,最简单的一个Shiro应用:

应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager;

我们需要给Shiro的SecurityManager注入Realm,从而让SecurityManager能得到合法的用户及其权限进行判断。

从以上也可以看出,Shiro不提供维护用户/权限,而是通过Realm让开发人员自己注入

实战

认证-授权一组合

配置设置fiter 根据对应的设置对应就好了

1注入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </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>

 


2编写自定义realm 实现realm 
     复写两个方法
     授权
           认证成功后 进行授权 
     认证
           一般在登陆时就认证 没通过一切免谈

package com.jc.springboot_shiro.shiro;

import com.jc.springboot_shiro.Service.UserService;
import com.jc.springboot_shiro.domain.User;
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;

public class UserRelam extends AuthorizingRealm {
    @Autowired
    UserService service;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//        授权 得要用户吧 subject可以得到用户
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        //获取用户的角色
        String role = user.getRole();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRole(role);


        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//        认证 首先得拿到 token令牌 token里面有账号密码
        UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
//        通过token来查有没有这个用户
        User user = service.findbyusername(token.getUsername());
        if(user !=null){
//            有这个用户 在比较密码 把正确密码带过去比对
            return new SimpleAuthenticationInfo(user,user.getPassword(),getName() );
        }

        return null;
    }
}

 


3编写配置类config shiroconfig 
  配置类三大金刚
ShiroFilterFactoryBean->SecurityManager->realm 
在bean里面编写内置过滤器 就是配置权限啥的 map

package com.jc.springboot_shiro.config;

import com.jc.springboot_shiro.shiro.UserRelam;
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 java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;


//    ShiroFilterFactoryBean:第三步
 @Configuration
    public class shiroconfig {
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
            ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
            //        设置安全管理器
            factoryBean.setSecurityManager(securityManager);
//            这里面写拦截 规则
//        添加shiro的内置过滤器
//            认证过滤器
            //anon:无需认证。
            //authc:必须认证。
            //authcBasic:需要通过 HTTPBasic 认证。
            //user:不一定通过认证,只要曾经被 Shiro 记录即可,比如:记住我。
            //授权过滤器
            //perms:必须拥有某个权限才能访问。
            //role:必须拥有某个角色才能访问。
            //port:请求的端口必须是指定值才可以。
            //rest:请求必须基于 RESTful,POST、PUT、GET、DELETE。
            //ssl:必须是安全的 URL 请求,协议 HTTPS。
            Map<String,String> map=new Hashtable<>();
//            new一个map存放信息
            map.put("/main","authc");
            map.put("/main","roles[admin]");
            //设置完权限后要放到fiter链里面
            factoryBean.setFilterChainDefinitionMap(map);

            return factoryBean;
        }
        //    DefaultWebSecurityManager:第二步
        @Bean
        public DefaultWebSecurityManager securityManager(@Qualifier("userRelam") UserRelam userRelam) {
            DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
            manager.setRealm(userRelam);
            return manager;
        }
        //    Realm:创建realm对象,需要自定义:第一步,从后往前配置
        @Bean
        public UserRelam userRelam() {
            return new UserRelam();
        }
    }

 


4salt盐 加密 我不会
5测试 使用


subject.login开始

  @GetMapping("/login")
    public String main(String username , String password, Model model){
        Subject subject = SecurityUtils.getSubject();
        //得到subject 用户
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        //获取账号密码 token令牌

        try {
            subject.login(token);
            //放进去认证

            return "main";
        } catch (AuthenticationException e) {
//            账号密码有问题 就会报错 然后catch异常就好了
            System.out.println(
                    "出错"
            );
            model.addAttribute("msg","账号密码错误");
            e.printStackTrace();
            return "login";
        }



    }

 


subject.logout结束

写个logout的 controller 就好了 

posted on 2022-02-03 18:25  ziwang520  阅读(26)  评论(0编辑  收藏  举报