详解Java springboot 整合Shiro框架

Shiro介绍

Shiro是一款安全框架,主要的三个类Subject、SecurityManager、Realm

  • Subject:表示当前用户
  • SecurityManager:安全管理器,即所有与安全有关的操作都会与SecurityManager交互;且其管理着所有Subject;可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC中DispatcherServlet的角色
  • Realm:Shiro从Realm 获取安全数据(如用户、角色、权限)

Shiro框架结构图

详解Java springboot 整合Shiro框架_第1张图片

Springboot整合Shiro

建项目是勾选spring web,导入依赖


        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        

        
            org.apache.shiro
            shiro-spring
            1.7.1
        

        
            org.projectlombok
            lombok
            true
            1.18.2
        

        
            mysql
            mysql-connector-java
        

        
            com.alibaba
            druid
            1.0.9
        

        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.1.1
        

        
            log4j
            log4j
            1.2.17
        

        
            com.github.theborakompanioni
            thymeleaf-extras-shiro
            2.0.0
        

编写页面及其控制层

详解Java springboot 整合Shiro框架_第2张图片

 转发的设置,全部编写在MVCConfig中的前端控制器中

@Configurationpublic class MyMvcConfig implements WebMvcConfigurer {    @Override    public void addViewControllers(ViewControllerRegistry registry) {        registry.addViewController("/").setViewName("index");        registry.addViewController("/login.html").setViewName("login");        registry.addViewController("/user/add").setViewName("user/add");        registry.addViewController("/user/update").setViewName("user/update");        registry.addViewController("/loginout").setViewName("login");    }}

连接数据库

编写application.yml

spring:
  datasource:
    username: ***
    password: ***
    url: jdbc:mysql://localhost:3306/db_2?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
   
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis:
  type-aliases-package: com.example.demo.pojo
 

编写 pojo、dao、service三层,dao层可以直接使Mybatis的注解。

需要的方法就是findByName(String username),通过表单传入的username值进行查询。

编写UserRealm 需要继承AuthorizingRealm

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private IuserService iuserService;
//    授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("===>授权");
        SimpleAuthorizationInfo Info = new SimpleAuthorizationInfo();
        //        获取登录对象
        Subject subject = SecurityUtils.getSubject();
        user principal = (user) subject.getPrincipal();//拿到user
        Info.addStringPermission(principal.getPerms());
        return Info;
    }
//    认证
 
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("==>认证");
        UsernamePasswordToken authenticationToken1 = (UsernamePasswordToken) authenticationToken;
        user byName = iuserService.findByName(authenticationToken1.getUsername());
        if(byName==null){
            return null;//抛出用户名错误的异常
        }
        //密码认证shiro自己完成  将user对象 传递给上面的方法进行授权
        return new SimpleAuthenticationInfo(byName,byName.getPassword(),"");
    }
}

代码的分析:

认证部分:

将表单提交的数据封装成一个对象,通过username从数据库中查询返回一个对象,进行比对

最后将这个查询的对象传递给授权方法。

授权部分:

获取到用户对象,给用户对象进行相应的授权。(传递的user对象中就有权限设置)

编写ShiroConfig

@Configuration
public class ShiroConfig {
    @Bean   //创建对象
    public UserRealm userRealm(){
        return new UserRealm();
    }
    @Bean   //接管对象  @Bean 默认使用方法名称
    public DefaultWebSecurityManager securityManager(@Qualifier("userRealm") Realm realm){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(realm);
        return defaultWebSecurityManager;
    }
    @Bean  //交给前端处理
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
 
        HashMap hashMap = new HashMap<>();
//        该路径 必须通过认证 才能进行访问
        hashMap.put("/user/*","authc");
//        进行授权
        hashMap.put("/user/add","perms[add]");
        hashMap.put("/user/update","perms[update]");
//        注销
        hashMap.put("/logout","logout");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(hashMap);
//        设置登录页面的路径
        shiroFilterFactoryBean.setLoginUrl("/login.html");
//        设置授权页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/noLogin");
        return shiroFilterFactoryBean;
    }
 
//    完成整合
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}

代码分析

在这个配置类中,配置的方法就是ioc注入。

ShiroFilterFactoryBean中可以配置

  • 资源路径对应的权限
  • 登陆页面
  • 权限不足 无法访问的页面路径
  • 注销

补充: 拦截的属性

  • anon: 无需认证就可以访问
  • authc: 必须认证了才能访问
  • user: 必须拥有记住我功能才能用
  • perms: 拥有对某个资源的权限才能访问
  • role: 拥有某个角色权限

编写控制层代码

@Controller
public class logincontroller {
//    执行流程 前端表单-》控制层代码-》config
    @PostMapping("/login")
    public String login(String username, String password, Model model){
//        获取一个用户
        Subject subject = SecurityUtils.getSubject();
//        封装用户登陆数据
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
//        执行登录方法,如果失败就会抛出异常
        try{
            subject.login(usernamePasswordToken);
            return "index";
        }catch (UnknownAccountException e){
            model.addAttribute("msg","用户名错误");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return "login";
        }
    }
    @GetMapping("/noLogin")
    @ResponseBody
    public String nologin(){return "未经授权 无法访问";}
 
}

代码分析:

login方法:获取从表单传递的数据,封装从UsernamePasswordToken对象,调用login方法进行登录操作

Shiro整合Thymeleaf

在ShiroConfig需要整合ShiroDialect

//    完成整合
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

约束

xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"

使用方法

  • shiro:notAuthenticated:没有进行登录 显示
  • shiro:authenticated:已经登陆 显示
  • shiro:hasPermission="A"  用户存在A的权限则显示

示例代码:




    
    Title


首页

ADD

总结

登录的流程:login表单-》loginController-》ShiroConfig-》UserRealm

效果:

点击登录,控制台会显示

详解Java springboot 整合Shiro框架_第3张图片

 进入add/update的页面,也会打印"===>授权",这个也证明了登录的执行流程

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

你可能感兴趣的:(详解Java springboot 整合Shiro框架)