栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot与Shiro整合详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot与Shiro整合详解

Shiro 1、简介
  1. Apache Shiro 是一个Java的安全(权限)框架 ------- 和SpringSecurity一样是安全框架
  2. Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在JavaSe环境.
  3. Shiro 可以完成: 认证,授权,加密,会话管理,Web集成,缓存等
  4. 下载地址:https://shiro.apache.org/ 官网
2、SpringBoot整合Shiro环境搭建
  1. 导入依赖
 
        
            org.apache.shiro
            shiro-spring
            1.4.1
        
  • springboot整合的shiro启动器并不好用,甚至会出现拦截器拦截不到的情况,所以还是用shiro-spring这个依赖
  1. 写html页面

add.html




    
    
    
    Document


增加页面

update.html




    
    
    
    Document


更新页面

index.html




    
    
    
    Document


首页


add | update

login.html




    
    Title


登录

username:

password:

  1. controller层映射
package com.example.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MyController {
    @RequestMapping("/")
    public String toIndex(Model model){
        model.addAttribute("msg","hello,shiro");
        return "index";
    }

    @RequestMapping("/user/add")
    public String add(){
        return "/user/add";
    }

    @RequestMapping("/user/update")
    public String update(){
        return "/user/update";
    }

    @RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }
    @RequestMapping("/login")
    public String login(String username,String password,Model model) {
        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);//执行登录的方法,如果没有异常就可以了
            return "index";
        } catch (UnknownAccountException e) {//用户名不存在
            model.addAttribute("msg", "用户名错误");
            return "login";
        } catch (IncorrectCredentialsException e) {//密码不存在
            model.addAttribute("msg", "密码错误");
            return "login";
        }
    }
}

3、Shiro实现功能
  1. shiro配置

ShiroConfig.java

package com.example.config;

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.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
    //ShiroFilterFactoryBean  第三步  关联第二步
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager")DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean =new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        //添加shiro的内置过滤器
        
        Map filterMap = new HashMap<>();
        filterMap.put("/user/add","anon");
        filterMap.put("/user/update","authc");
        //设置访问不了时跳转到登录页面
        bean.setLoginUrl("/toLogin");
        bean.setFilterChainDefinitionMap(filterMap);
        return bean;
    }
    //DefaultWebSecurityManager  第二步  关联第一步
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联userRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }




    // 创建realm对象,需要自定义类 第一步
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }
}

  1. 创建userRealm对象

UserRealm.java

package com.example.config;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class UserRealm extends AuthorizingRealm {

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        System.out.println("执行了=>授权doGetAuthorizationInfo");
        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了=>认证doGetAuthenticationInfo");
        //用户名和密码认证  数据库中取
        String name = "root";
        String password="123456";
         UsernamePasswordToken userToken = (UsernamePasswordToken)token;
         if (!userToken.getUsername().equals(name)){
             return null; //抛出异常,异常就是前面自定义的 UnknownAccountException e
         }
         //密码认证不需要我们做,shiro会自动做
        return new SimpleAuthenticationInfo("",password,"");
    }
    //授权

}

  1. 登录拦截
  @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager")DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean bean =new ShiroFilterFactoryBean();
            //设置安全管理器
            bean.setSecurityManager(defaultWebSecurityManager);
            //添加shiro的内置过滤器
            
            Map filterMap = new HashMap<>();
            filterMap.put("/user/add","anon");
            filterMap.put("/user/update","authc");
            //设置访问不了时跳转到登录页面
            bean.setLoginUrl("/toLogin");
            bean.setFilterChainDefinitionMap(filterMap);
            return bean;
        }

记得要用bean注入,不然拦截不了

  1. 实现用户认证

MyControlller.java

  @RequestMapping("/login")
    public String login(String username,String password,Model model) {
        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);//执行登录的方法,如果没有异常就可以了
            return "index";
        } catch (UnknownAccountException e) {//用户名不存在
            model.addAttribute("msg", "用户名错误");
            return "login";
        } catch (IncorrectCredentialsException e) {//密码不存在
            model.addAttribute("msg", "密码错误");
            return "login";
        }
    }

UserRealm.java

 //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了=>认证doGetAuthenticationInfo");
        //用户名和密码认证  数据库中取
        String name = "root";
        String password="123456";
         UsernamePasswordToken userToken = (UsernamePasswordToken)token;
         if (!userToken.getUsername().equals(name)){
             return null; //抛出异常,异常就是前面自定义的 UnknownAccountException e
         }
         //密码认证不需要我们做,shiro会自动做
        return new SimpleAuthenticationInfo("",password,"");
    }
    //授权
  1. 退出注销功能
  • 在index页面设计退出按钮
注销
  • myController中去映射
  @RequestMapping("/logout")
    public String logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "index";
    }
4、Shiro整合Mybatis
  1. 导入mysql依赖

    
    
            
                org.projectlombok
                lombok
            
            
                mysql
                mysql-connector-java
            
    
            
                log4j
                log4j
                1.2.12
            
    
            
                com.alibaba
                druid
                1.2.3
            
    
            
                org.mybatis.spring.boot
                mybatis-spring-boot-starter
                2.2.2
            
    
  2. 配置数据源以及绑定mybatis

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    password: 123456
    username: root
    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8
    type: com.alibaba.druid.pool.DruidDataSource

    #SpringBoot默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true


    #配置监控统计拦截的filters,  stat:监控统计 , log4j:日志记录 , wall:防御sql注入
    #如果运行时报错,导入log4j即可(maven)
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500


#整合mybatis
mybatis:
  type-aliases-package: com.example.pojo
  mapper-locations: classpath:mapper
            //拦截
            Map filterMap = new HashMap<>();
            //设权限,登录后要进入add必须有进入add页面的权限user:add
            filterMap.put("/user/add","perms[user:add]");//给add页面设置权限
            filterMap.put("/user/update","perms[user:update]");//给update页面设置权限
            //设权限,要进入user/下的页面需要登录
            filterMap.put("/user/*","authc");


            //设置访问不了时跳转到登录页面
            bean.setLoginUrl("/toLogin");
            //设置未授权页面
            bean.setUnauthorizedUrl("/noauth");
            bean.setFilterChainDefinitionMap(filterMap);
            return bean;
        }
        //DefaultWebSecurityManager  第二步  关联第一步
        @Bean
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联userRealm
            securityManager.setRealm(userRealm);
            return securityManager;
        }




        // 创建realm对象,需要自定义类 第一步
        @Bean
        public UserRealm userRealm(){
            return new UserRealm();
        }
    }

  1. UserRealm.java
package com.example.config;

import com.example.pojo.User;
import com.example.service.UserServiceImpl;
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 UserRealm extends AuthorizingRealm {
    @Autowired
    UserServiceImpl userService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        System.out.println("执行了=>授权doGetAuthorizationInfo");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //拿到当前登录的对象
        Subject subject = SecurityUtils.getSubject();
        User currentUser =(User) subject.getPrincipal(); //拿到User对象
        //设置当前用户的权限
        if (currentUser.getPerms()!=null) {
            info.addStringPermission(currentUser.getPerms());//如果当前用户有权限,就添加授权
            return info;
        }
        else {
            return null;  //如果没有有返回null
        }

    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了=>认证doGetAuthenticationInfo");
//        //用户名和密码认证  数据库中取
//        String name = "root";
//        String password="123456";
        UsernamePasswordToken userToken = (UsernamePasswordToken)token;
        //连接真实数据库来验证
        User user = userService.queryUserByName(userToken.getUsername());
        if (user==null){//说明没有这个人
            return null;  //走到前面的异常UnknownAccountException
        }
        //数据库中这个人就继续进行密码验证,加密了
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");

    }
    //授权

}

6、Shiro整合thymeleaf
  1. 导入依赖

        
            com.github.theborakompanioni
            thymeleaf-extras-shiro
            2.1.0
        
  1. 在前端实现,登录账号后,有这个权限的人才能看到进入这个页面的入口

add
  1. 设计一个登录的按钮,并且登录过后便不需要再显示这个登录入口(即判断有无session)
  • 获取session从登录认证的地方

UserRealm.java

 Subject currentSubject = SecurityUtils.getSubject();
        Session session = currentSubject.getSession();
        session.setAttribute("loginUser",user);
  • 前端实现

  • 运行测试
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1035242.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号