springboot整合shiro 入门学习

2 篇文章 0 订阅
1 篇文章 0 订阅

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中的授权方法是在用户访问需要权限的页面才会执行。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值