微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

springboot整合shiro简单使用(查询数据库)

shiro主要实现认证和授权的问题

认证确认用户身份,授权对用户访问资源的权限做控制

建表语句

CREATE TABLE `user` (
   id INT(11) PRIMARY KEY AUTO_INCREMENT  COMMENT '主键',
  `name` VARCHAR(255)  COMMENT '用户名',
  `password` VARCHAR(255)  COMMENT '密码'
)
INSERT INTO `user`(`name`,`password`) VALUES('test','123456')
CREATE TABLE `role` (
   id INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL  COMMENT '主键',
   role_name VARCHAR(255) DEFAULT NULL COMMENT '角色名称',
  user_id VARCHAR(255) DEFAULT NULL COMMENT '用户id'
)

INSERT INTO `role`(role_name,user_id) VALUES('admin','1')

CREATE TABLE permission (
   id INT(11) PRIMARY  KEY AUTO_INCREMENT NOT NULL  COMMENT '主键',
   permission VARCHAR(255) DEFAULT NULL COMMENT '权限',
  role_id VARCHAR(255) DEFAULT NULL COMMENT '角色id'
)
INSERT INTO permission(permission,role_id) VALUES
('create','1'),
('query','1')

  

 

 

 

 

 

 代码部分

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/>
    </parent>

    <groupId>com.java</groupId>
    <artifactId>shiro-service</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--springboot整合mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
        <!--MysqL驱动5.6.17-->
        <dependency>
            <groupId>MysqL</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.4</version>
        </dependency>
        <!--页面模板依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--热部署依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

  

server.port=8001

logging.level.com.java=debug
logging.level.web=debug
spring.devtools.add-properties=false

spring.datasource.driver-class-name=com.MysqL.jdbc.Driver
#spring.datasource.url=jdbc:MysqL://127.0.0.1:3306/spring_shiro?useUnicode=true&characterEncoding=utf-8&useSSL=false
#spring.datasource.username=root
#spring.datasource.password=root

mybatis.mapper-locations=classpath:mapping/*.xml
mybatis.configuration.map-underscore-to-camel-case=true 

spring.aop.proxy-target-class=true

  

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java.mapper.PermissionMapper">

    <insert id="addBatchPermission" parameterType="java.util.List">
        INSERT INTO permission(permission,role_id) VALUES
        <foreach collection="list" item="item" separator=",">
            (#{item.permission},#{item.roleId})
        </foreach>
    </insert>



</mapper>

  

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java.mapper.UserMapper">

    <resultMap id="userMap" type="com.java.bean.User">

        <result property="name" column="name"/>
        <result property="password" column="password"/>
        <collection property="roles" ofType="com.java.bean.Role">
            <result property="roleName" column="role_name"/>
            <collection property="permissions" ofType="com.java.bean.Permission">
                <result property="permission" column="permission"/>
            </collection>
        </collection>
    </resultMap>

      <select id="getListByBean" resultMap="userMap">
            SELECT  a.`name`,a.`password`,b.`role_name`,c.`permission`
         FROM  `user` a INNER JOIN  `role` b ON a.id=b.user_id INNER JOIN permission c ON b.id=c.role_id
      </select>

</mapper>

  

package com.java;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author yourheart
 * @Description
 * @create 2022-05-03 20:30
 */
@SpringBootApplication
public class ShiroApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShiroApplication.class,args);
    }
}

  

package com.java.bean;

import lombok.Data;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-15 1:54
 */
@Data
public class Permission {


    private Integer id;

    private String permission;

    private Integer roleId;
}


package com.java.bean;

import lombok.Data;

/**
 * @author yourheart
 * @Description
 * @create 2021-09-17 23:54
 */
@Data
public class ResponseBean {
    /**
     * 状态码
     */
    private String code;
    /**
     * 返回值
     */
    private String msg;
    /**
     * 拓展字段
     */
    private Object extraInfo;
}


package com.java.bean;

import lombok.Data;

import java.util.List;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-15 1:55
 */
@Data
public class Role {


    private Integer id;

    private String roleName;

   private Integer userId;

    private List<Permission> permissions;
}


package com.java.bean;

import lombok.Data;

import java.util.List;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-15 1:53
 */
@Data
public class User {


    private Integer id;

    private String name;

    private Integer password;

    private List<Role> roles;
}

  

package com.java.mapper;

import com.java.bean.Permission;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-25 8:37
 */
@Mapper
public interface PermissionMapper {


    @Select("SELECT  permission FROM  permission  WHERE role_id=#{roleId}")
    List<Permission> findPermission(Integer roleId);

    int addBatchPermission(List<Permission> permissions);

}


package com.java.mapper;

import com.java.bean.Role;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-25 8:37
 */
@Mapper
public interface RoleMapper {

    @Select("SELECT  * FROM `role` r  WHERE user_id =#{id}")
    List<Role> findRoleById(Integer id);


    @Insert("INSERT INTO `role`(role_name,user_id) VALUES(#{roleName},#{userId})")
    int addRole(Role role);
}


package com.java.mapper;

import com.java.bean.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-25 8:10
 */
@Mapper
public interface UserMapper {

    @Select("SELECT  *  FROM  `user` WHERE `name`=#{name}")
    User findByName(@Param("name") String name);

    @Select("SELECT  COUNT(*)  FROM  `user` WHERE `name`=#{name} AND `password`=#{password}")
    int selectUserExists(User user);

    @Insert("INSERT INTO `user`(`name`,`password`) VALUES(#{name},#{password})")
    int addUser(User user);

    @Select("SELECT  *  FROM  `user` WHERE id=#{id}")
    User findById(Integer id);

    @Select("SELECT  a.`name`,a.`password`,b.`role_name`,c.`permission`  \n" +
            "FROM  `user` a INNER JOIN  `role` b ON a.id=b.user_id INNER JOIN permission c ON b.id=c.role_id")
    List<Map<String,Object>> getList();


    List<User> getListByBean();


}

  

package com.java.service;

import com.java.bean.ResponseBean;
import com.java.bean.User;

public interface UserService {

    /**
     * 通过用户名查询用户的权限
     * @param name
     * @return
     */
    User getUserByName(String name);


    /**
     * 添加用户认给query权限
     * @param user
     * @return
     */
    ResponseBean addUser(User user);
}


package com.java.service.impl;

import com.java.bean.Permission;
import com.java.bean.ResponseBean;
import com.java.bean.Role;
import com.java.bean.User;
import com.java.mapper.PermissionMapper;
import com.java.mapper.RoleMapper;
import com.java.mapper.UserMapper;
import com.java.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-24 20:34
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;


    /**
     * 通过用户名查询用户的权限
     *
     * @param name
     * @return
     */
    @Override
    public User getUserByName(String name) {
        User user = userMapper.findByName(name);
        List<Role> roleByName = roleMapper.findRoleById(user.getId());

        roleByName.forEach(role -> {
            List<Permission> permissionList = permissionMapper.findPermission(role.getId());
            role.setPermissions(permissionList);
        });
        user.setRoles(roleByName);
        return user;
    }

    /**
     * 添加用户认给query权限
     *
     * @param user
     * @return
     */
    @Override
    public ResponseBean addUser(User user) {


        ResponseBean responseBean=new ResponseBean();

        int selectUserExists = userMapper.selectUserExists(user);
        if (selectUserExists==1){
            responseBean.setCode("-100");
            responseBean.setMsg("用户已经存在");
            return responseBean;
        }
        //入参需要用户名和密码
        int addUser = userMapper.addUser(user);

        //通过用户名查询返回用户的id,向角色表中存放用户的角色和用户的id
        User byName = userMapper.findByName(user.getName());
        Role role=new Role();
        role.setRoleName("common");
        role.setUserId(byName.getId());
        int addRole = roleMapper.addRole(role);

        //查询角色的id,向权限表存放角色的权限和角色id
        List<Role> roleById = roleMapper.findRoleById(byName.getId());

        roleById.forEach(r->{
            Integer rId = r.getId();
            List<Permission> permissions=new ArrayList<>();
            Permission permission=new Permission();
            permission.setPermission("query");
            permission.setRoleId(rId);
            permissions.add(permission);
            permissionMapper.addBatchPermission(permissions);
        });

        responseBean.setCode("100");
        responseBean.setMsg("用户添加成功");
        return responseBean;

    }
}

  shiro权限控制部分

package com.java.config;

import com.java.bean.Permission;
import com.java.bean.Role;
import com.java.bean.User;
import com.java.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.springframework.beans.factory.annotation.Autowired;


/**
 * @author yourheart
 * @Description 实现AuthorizingRealm接口用户用户认证
 * @create 2022-06-15 1:56
 */
@Slf4j
public class MyShiroRealm extends AuthorizingRealm {


    @Autowired
    private UserService userService;

    /**
     * 角色权限和对应权限添加
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取登录用户名
        String name = (String) principalCollection.getPrimaryPrincipal();
        log.info("【角色权限和对应权限添加】name:{}", name);
        //查询用户名称
        User user = userService.getUserByName(name);
        log.info("【角色权限和对应权限添加】user:{}", user);
        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        for (Role role : user.getRoles()) {
            //添加角色
            simpleAuthorizationInfo.addRole(role.getRoleName());
            for (Permission permission : role.getPermissions()) {
                //添加权限
                simpleAuthorizationInfo.addStringPermission(permission.getPermission());
            }
        }
        return simpleAuthorizationInfo;
    }

    /**
     * 用户认证
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //加这一步的目的是在Post请求的时候会先进认证,然后在到请求
        log.info("【用户认证】authenticationToken.getPrincipal():{}", authenticationToken.getPrincipal());
        if (authenticationToken.getPrincipal() == null) {
            return null;
        }
        //获取用户信息
        String name = authenticationToken.getPrincipal().toString();
        log.info("【用户认证】name:{}", name);
        User user = userService.getUserByName(name);
        log.info("【用户认证】user:{}", user);
        if (user == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getpassword().toString(), getName());
            return simpleAuthenticationInfo;
        }
    }
}




package com.java.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterfactorybean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @author yourheart
 * @Description
 * @create 2022-06-15 1:58
 */
@Configuration
@Slf4j
public class ShiroConfiguration {

    /**
     * 将自己的验证方式加入容器
     *
     * @return
     */
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }

    /**
     * 权限管理,配置主要是Realm的管理认证
     *
     * @return
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    /**
     * Filter工厂,设置对应的过滤条件和跳转条件
     *
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterfactorybean shiroFilterfactorybean(SecurityManager securityManager) {
        ShiroFilterfactorybean shiroFilterfactorybean = new ShiroFilterfactorybean();
        shiroFilterfactorybean.setSecurityManager(securityManager);
        Map<String, String> map = new HashMap<String, String>();
        //登出
        map.put("/logout", "logout");
        /**
         * Shiro内置过滤器,能够实现拦截器相关的拦截器
         *    经常使用的过滤器:
         *      anon:无需认证(登陆)能够访问
         *      authc:必须认证才能够访问
         *      user:若是使用rememberMe的功能能够直接访问
         *      perms:该资源必须获得资源权限才能够访问
         *      role:该资源必须获得角色权限才能够访问
         **/
        //对所有用户认证
        map.put("/**", "authc");

        map.put("/re", "anon");


        //登录
        shiroFilterfactorybean.setLoginUrl("/login");
        //首页
        shiroFilterfactorybean.setSuccessUrl("/index");
        //错误页面,认证不通过跳转
        shiroFilterfactorybean.setUnauthorizedUrl("/error");
        shiroFilterfactorybean.setFilterChainDeFinitionMap(map);
        return shiroFilterfactorybean;
    }

    /**
     * 加入注解的使用,不加入这个注解不生效
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

  

package com.java.controller.front;

import com.java.bean.Role;
import com.java.bean.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnkNownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;


/**
 * @author yourheart
 * @Description
 * @create 2022-06-15 2:11
 */
@RestController
@Slf4j
public class TestController {

    @PostMapping("/login")
    public String login(@RequestBody User user) {
        if (StringUtils.isEmpty(user.getName()) || StringUtils.isEmpty(user.getpassword())) {
            return "请输入用户名和密码!";
        }
        //用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
                user.getName(),
                String.valueOf(user.getpassword())
        );
        try {
            //进行验证,这里可以捕获异常,然后返回对应信息
            subject.login(usernamePasswordToken);
        } catch (UnkNownAccountException e) {
            log.error("用户名不存在!", e);
            return "用户名不存在!";
        } catch (AuthenticationException e) {
            log.error("账号或密码错误!", e);
            return "账号或密码错误!";
        } catch (AuthorizationException e) {
            log.error("没有权限!", e);
            return "没有权限";
        }
        return "login success";
    }


    /**
     * 用户登出
     * @return
     */
    @RequestMapping("/loginout")
    public String loginout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return  "退出成功";
    }

    @RequiresPermissions("query")
    @RequestMapping(value = "/index")
    @ResponseBody
    public String index(){
        return "进入主页";
    }



    @RequiresPermissions("create")
    @GetMapping("/add")
    public String add() {
        return "add success!";
    }


    @RequestMapping(value = "/re")
    @ResponseBody
    public String re(){
        return "进入注册页面";
    }


    @RequestMapping(value = "/log")
    @ResponseBody
    public String log(){
        return "进入日志页面";
    }

}

  

 

 附上测试地址

http://127.0.0.1:8001/login

{
    "name":"qiuxie",
    "password":"123"
}

http://127.0.0.1:8001/index

http://127.0.0.1:8001/add

用户登出
http://127.0.0.1:8001/loginout

  

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐