springboot整合shiro 入门学习

dependencies:

		<!--
		 	Subject  用户
		 	SecurityManager  管理所有用户
		 	Realm  连接数据
		 -->
		<!--shrio整合spring的包 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.3.2</version>
		</dependency>

		<!--thymeleaf 模板依赖 -->
		<dependency>
			<groupId>org.thymeleaf</groupId>
			<artifactId>thymeleaf-spring5</artifactId>
		</dependency>
		<dependency>
			<groupId>org.thymeleaf.extras</groupId>
			<artifactId>thymeleaf-extras-java8time</artifactId>
		</dependency>

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

		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.12</version>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.12</version>
		</dependency>

		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.1.0</version>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.16.10</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.13</version>
		</dependency>

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

thymleaf命名空间: 

<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"> <!--thymeleaf整合shiro 的命名空间 -->

shiro 核心组件

Subject、SecurityManager、Realm

 

springboot项目环境搭建完毕后,对shiro进行配置(使用java配置类方式)

@Configuration
public class ShiroConfig {

    //第三步 : ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager defaultWebSecurityManager ){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);

        //添加shiro的内置过滤器
        /**
         * anon:无需认证就可以访问
         * authc:必须认证了才能访问
         * user:必须拥有记住我功能才能使用
         * perms:拥有对某个资源的权限才能访问
         * role:属于某些角色才能访问
         */
        Map<String,String> filterMap = new LinkedHashMap<>();
        // 前端控制器(controller) /user下面的资源需要认证后才能访问,不然会跳转到登陆页面
        //认证
        filterMap.put("/user/add","authc");
        filterMap.put("/user/update","authc");
        //授权,正常的情况下跳转到未授权页面
        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/update","perms[user:update]");

        bean.setFilterChainDefinitionMap(filterMap);

        //未登陆页面
        bean.setLoginUrl("/toLogin");
        //未授权页面
        bean.setUnauthorizedUrl("/noauth");

        return bean;
    }

    //第二部 : DefaultWebSecurityManager
    @Bean(name="securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        securityManager.setRealm(userRealm);
        return securityManager;
    }

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

    //整合ShiroDialect:用来整合shiro和thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

}

  自定义Realm 、DefaultWebSecurityManager、ShiroFilterFactoryBean,并将其注入到spring 的IOC容器中,其中三个组件之间的引用是通过@Qualifier("")标签引用的IOC 容器中的对象

  在ShiroFilterFactoryBean中指定页面访问所需要的权限信息

 

自定义Realm并继承AuthorizingRealm:

//自定义的UserRealm
public class UserRealm extends AuthorizingRealm{

    @Autowired
    UserServiceImpl userService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权doGetAuthorizationInfo");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登陆的对象
        Subject subject = SecurityUtils.getSubject();
        //获取认证方法中传入的登陆对象
        User currentUser = (User) subject.getPrincipal();
        //设置当前登陆对象的权限(它在数据库中对应的权限)
        info.addStringPermission(currentUser.getPerms());
        //添加session
        Session session = subject.getSession();
        session.setAttribute("loginUser",currentUser);
        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了认证doGetAuthenticationInfo");
        //对传递进来的token进行格式的转换
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        //在数据库中根据用户名查询是否存在该用户
        User user = userService.queryUserByName(userToken.getUsername());
        //判断用户是否存在
        if (user==null){
            return null;    //抛出UnknownAccountException 异常
        }
        //密码认证,shiro做               把user传入principal中,则在授权方法中可以使用getPrincipal方法获取数据库中的user
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
//注意,shiro自动验证密码要传入数据库中存放的密码,shiro自动将改密码与用户登陆时的密码进行校验
    }
}

Controller:

@Controller
public class IndexController {
    @RequestMapping({"index","/"})
    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);
        //记住我功能: token.setRememberMe(true);
        try{
            subject.login(token); //执行登陆方法,没有异常就OK了
            //注销功能:subject.logout();
            return "/index";
        }catch(UnknownAccountException e){ //用户名不存在
            model.addAttribute("msg","用户名不存在");
            return "/login";
        }catch(IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return "/login";
        }
    }

    @RequestMapping("/noauth")
    @ResponseBody
    public String unauthorized(){
        return "未经授权无法访问此页面";
    }
}

index:

 

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"> <!--thymeleaf整合shiro 的命名空间 -->
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>首页</h1>
    <h3 th:text="${msg}"></h3>
    <a href="/toLogin">登陆</a>
    <hr>
    <div shiro:hasPermission="user:add"> <!--使用shiroDialect 继承了shiro和thymeleaf,当用户没有user:add权限时,不显示里面的a标签 -->
        <a href="/user/add">add</a><br>
    </div>
    <div shiro:hasPermission="user:update">
        <a href="/user/update">update</a><br>
    </div>
</body>
</html>

项目目录结构截图:

 

坑:

shiro的授权过程,即自定义realm中的授权方法是在用户访问需要权限的页面才会执行。

 
适用人群 Java开发人员,Vue开发人员,前后端分离开发人员,权限管理和配置开发人员 课程概述 【讲师介绍】       现某知名大型互联网公司资深架构师,技术总监,职业规划师,首席面试官,曾在某上市培训机构,高校任教多年。      Array(Array老师)10多年互联网公司实战经验,知名的大型互联网公司的架构师,高管等职,在企业长期从事于技术的源码阅读和新技术的研究;擅长于职业规划,面试辅导,从事面试官多年  技术选型 开发环境:Eclipse/Idea ,JDK 1.8以上  后端技术 核心框架:SpringBoot2.x框架系列(同样适用Springcloud F版本以后的版本),如下(节选):     持久层框架:MyBatis 3.x + Mybatis-plus 3.x 日志管理:SLF4J 1.7 + Log4j2 2.7 工具类:Apache Commons、Jackson 、fastjson、Gson 权限验证 前端技术   Vue   Vue-cli ElementUI ---https://element.eleme.io/ JSX (JavaScript Xml) 前台的权限验证和路由设置 开发模式        前后端分离的开发 数据库        Mysql5 IDE     Intellij Idea 【课程收益】 学完课程能独立完成springboot2+vue+elementUI的整合项目开发(前后端分离)  学完课程能Shiro的权限控制,按钮级别的权限控制  学完课程能独立后端开发和独立前端开发Vue  学完课程能快速的掌握目前互联网用的前沿的框架和技术实战
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页