SpringBoot整合Shiro

Posted 誓什么言

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot整合Shiro相关的知识,希望对你有一定的参考价值。

导入Pom.xml

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

创建Shiro核心类

package com.shiyan.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
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.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    //ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        //配置shiro内置管理器
        Map<String,String> map = new LinkedHashMap<>();
        /**
         * anno 无需验证即可登录
         * authc 验证后才能登陆
         * user  拥有记住我功能后才能使用
         * perms 拥有对某个资源的权限才能访问
         * role  拥有某个角色才能访问
         */
        map.put("/user/add","perms[user:add]");
        map.put("/user/update","perms[user:update]");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        //设置登录的请求
        shiroFilterFactoryBean.setLoginUrl("/toLogin");

        //设置为授权的页面请求
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
        return shiroFilterFactoryBean;
    }

    //创建DefaultWebSecurityManager
    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager defaultSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }


    //创建realm对象  需要自定义 继承AuthorizingRealm
    @Bean//bean的id默认为方法名
    public UserRealm userRealm(){
        return new UserRealm();
    }

    //Shiro和Thymeleaf整合   用于thymeleaf模板使用shiro标签
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}

认证以及授权

package com.shiyan.config;

import com.shiyan.pojo.Users;
import com.shiyan.service.impl.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.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @ProjectName: SpringBoot
 * @Package: com.shiyan.config
 * @ClassName: UserRealm
 * @Author: DANGEROUS
 * @Description:
 * @Date: 2020/1/3 13:56
 * @Version: 1.0
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserServiceImpl service;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Users user = (Users) principalCollection.getPrimaryPrincipal();
        //数据库中查询相应权限并且授权
        info.addStringPermission(user.getPerms());
        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //System.out.println("执行了认证");

        //模拟数据库信息
//        String username = "root";
//        String password = "123456";

        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //数据库中获取用户信息
        Users users = service.queryOne(token.getUsername());
        if(users==null){//没有查询出这个用户名,数据库没有这个人
            return null;//抛出   UnknownAccountException 用户名有误
        }

        //将查询出来的user放进shiro的session中
        Subject currentUser = SecurityUtils.getSubject();
        Session session = currentUser.getSession();
        session.setAttribute("loginUser",currentUser);

        //密码认证Shiro做
        return new SimpleAuthenticationInfo(users,users.getPassword(),"");
    }
}

UserController

package com.shiyan.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


@Controller
public class UserController {

    @RequestMapping({"/","/index"})
    public String toIndex(Model model){
        model.addAttribute("msg","欢迎来到首页!!!");
        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";
        }
    }

    @ResponseBody
    @RequestMapping("/unauth")
    public String unauth(){
        return "未经授权无法访问。。。。";
    }

    @RequestMapping("/logout")
    public String logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "redirect:/toLogin";
    }

}

index.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
    <!--没有认证-->
<div shiro:notAuthenticated="">
    <a th:href="@{/toLogin}">登陆</a>
</div>
    <!--通过认证-->
<div shiro:authenticated="">
    <a th:href="@{/logout}">注销</a>
</div>
<div th:text="${msg}"></div>
<hr>
<div shiro:hasPermission="user:add">
    <a th:href="@{/user/add}">add</a><br>
</div>
<div shiro:hasPermission="user:update">
    <a th:href="@{/user/update}">update</a>
</div>
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>登陆</h1>
<hr>
<div style="text-align: center">
    <form action="/login" method="post">
        <span style="color: crimson" th:text="${msg}"></span>
        <p>用户名:<input type="text" name="username"></p>
        <p>密码:<input type="password" name="password"></p>
        <p><input type="submit" value="登陆"></p>
    </form>
</div>
</body>
</html>

前台Shiro标签

guest标签
  <shiro:guest>
  </shiro:guest>
  用户没有身份验证时显示相应信息,即游客访问信息。

user标签
  <shiro:user>  
  </shiro:user>
  用户已经身份验证/记住我登录后显示相应的信息。

authenticated标签
  <shiro:authenticated>  
  </shiro:authenticated>
  用户已经身份验证通过,即Subject.login登录成功,不是记住我登录的。

notAuthenticated标签
  <shiro:notAuthenticated>
  
  </shiro:notAuthenticated>
  用户已经身份验证通过,即没有调用Subject.login进行登录,包括记住我自动登录的也属于未进行身份验证。

principal标签
  <shiro: principal/>
  
  <shiro:principal property="username"/>
  相当于((User)Subject.getPrincipals()).getUsername()。

lacksPermission标签
  <shiro:lacksPermission name="org:create">
 
  </shiro:lacksPermission>
  如果当前Subject没有权限将显示body体内容。

hasRole标签
  <shiro:hasRole name="admin">  
  </shiro:hasRole>
  如果当前Subject有角色将显示body体内容。

hasAnyRoles标签
  <shiro:hasAnyRoles name="admin,user">
   
  </shiro:hasAnyRoles>
  如果当前Subject有任意一个角色(或的关系)将显示body体内容。

lacksRole标签
  <shiro:lacksRole name="abc">  
  </shiro:lacksRole>
  如果当前Subject没有角色将显示body体内容。

hasPermission标签
  <shiro:hasPermission name="user:create">  
  </shiro:hasPermission>

以上是关于SpringBoot整合Shiro的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot整合Shiro实现权限控制

SpringBoot整合Shiro实现权限控制

SpringBoot学习- 8整合Shiro

Shiro整合Springboot缓存之Redis实现

Springboot整合Shiro

SpringBoot整合Shiro 四:认证+授权