SpringBoot整合shiro(一)

◇◆丶佛笑我妖孽 提交于 2020-02-25 09:12:37

项目结构
在这里插入图片描述

spring和shiro的整合依赖

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency

yml文件配置

server:
  port: 8081
spring:
  application:
    name: ihrm-company #指定服务名
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shiro_db?useUnicode=true&characterEncoding=utf8
    username: root
    password: root
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true

  redis:
    host: 127.0.0.1
    port: 6379

userController的代码编写



import cn.itcast.shiro.domain.User;
import cn.itcast.shiro.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;
import java.util.Enumeration;

@RestController
public class UserController {

    @Autowired
    private UserService userService;
    //添加
    //使用shiro注解鉴权
    //@RequiresPermissions()    //访问次方法必须具备的权限
    //  @RequiresRoles()    //访问此方法必须具备的角色

    /**
     * 鉴权的方式
     * 1.过滤器: 如果权限信息不匹配跳转到 filterFactory.setUnauthorizedUrl("");  配置的URL
     * 2. 注解: 抛出异常
     */
    @RequiresPermissions("user-home")
    @RequestMapping(value = "/user/home")
    public String home() {
        return "访问主页成功";
    }

    //添加
    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public String add() {
        return "添加用户成功";
    }

    //查询
    @RequestMapping(value = "/user", method = RequestMethod.GET)
    public String find() {
        return "查询用户成功";
    }

    //更新
    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
    public String update(String id) {
        return "更新用户成功";
    }

    //删除
    @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
    public String delete() {
        return "删除用户成功";
    }

    /**
     * 1.传统登录
     * 前端发送登录请求 -》接口部分获取用户名密码 -》程序员在接口部分手动控制
     * <p>
     * 2.shiro登录
     * 前端发送登录请求-》接口部分获取用户名密码-》通过subject.login -》 realm域的认证方法
     *
     * @param username
     * @param password
     * @return
     */
    //用户登录
    @RequestMapping(value = "/login")
    public String login(String username, String password) {
        //构造登录令牌
        try {
            /**
             * 密码加密:
             *      shiro提供的md5加密
             *      参数一:加密的内容
             *      参数二:盐(加密的混淆字符串)  (可以用用户名,如果用户名不能改变)
             *      参数三:加密次数
             */
            password = new Md5Hash(password, username, 3).toString();
            UsernamePasswordToken upToken = new UsernamePasswordToken(username, password);
            //1.获取subject
            Subject subject = SecurityUtils.getSubject();
            //2.调用subject进行登录
            subject.login(upToken);
            return "登录成功";
        } catch (Exception e) {
            return "用户名或密码错误";
        }
    }

    @RequestMapping(value = "/autherror")
    public String autherror(int code) {
        return code == 1 ? "未登录" : "未授权";
    }
}

自定义realm

package cn.itcast.shiro.realm;

import cn.itcast.shiro.domain.Permission;
import cn.itcast.shiro.domain.Role;
import cn.itcast.shiro.domain.User;
import cn.itcast.shiro.service.UserService;
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.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

/**
 * 自定义realm
 */
public class CustomRealm extends AuthorizingRealm {
    public void setName(String name) {
        super.setName("custRealm");
    }

    @Autowired
    private UserService userService;

    /**
     * 授权方法
     * 操作时候,判断用户是否具有相应的权限
     * 先认证---安全数据
     * 再授权---根据安全数据获取用户具有的所有操作权限
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1.获取已认证的用户数据
        User user = (User) principalCollection.getPrimaryPrincipal();  //得到唯一的安全数据
        //2.根据用户数据获取用户的权限信息(所有色色,所有权限)
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> roles = new HashSet<>();  //所有色色
        Set<String> perms = new HashSet<>();  //所有权限
        for (Role role : user.getRoles()) {  //得到每一个角色
            roles.add(role.getName());  //得到角色名
            for (Permission perm : role.getPermissions()) {
                perms.add(perm.getCode());    //得到所有权限编码
            }
        }
        info.setStringPermissions(perms);
        info.setRoles(roles);
        return info;
    }


    /**
     * 认证方法
     *
     * @param authenticationToken 传递的用户名和密码
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.获取登录的用户名和密码(token)
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        String username = upToken.getUsername();
        String password = String.valueOf(upToken.getPassword());
        //2.根据用户名查询数据库
        User user = userService.findByName(username);
        //3.判断用户是否存在或密码一致
        if (user != null && user.getPassword().equals(password)) {
            //4.如果一致返回安全数据
            //构造方法:参数:  安全数据,密码,realm域名
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
            return info;
        }
        //5.不一致,返回null 抛出异常
        return null;
    }
}

shiro统一配置

package cn.itcast.shiro;

import cn.itcast.shiro.realm.CustomRealm;
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.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {

    //1.创建realm
    @Bean
    public CustomRealm getRealm() {
        return new CustomRealm();
    }

    //2.创建安全管理器
    @Bean
    public SecurityManager getSecurityManager(CustomRealm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;
    }

    /**
     * 在web程序中,shiro进行权限控制全部是通过一组过滤器集合进行控制
     *
     * @param securityManager
     * @return
     */
    //3.配置shiro的过滤器工厂
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        //1.创建过滤器工厂
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
        //2.设置安全管理器
        filterFactory.setSecurityManager(securityManager);
        //3.通用配置(跳转登录页面,未授权跳转的页面)
        filterFactory.setLoginUrl("/autherror?code=1");  //跳转url地址
        filterFactory.setUnauthorizedUrl("/autherror?code=2");  //未授权的url
        //4.设置过滤器集合
        /**
         * 设置所有的过滤器:有顺序 map
         * key=拦截的URL地址
         * value=过滤器类型
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
        // filterMap.put("/user/home","anon"); //当前请求地址可以匿名访问
        // 具有某种权限才能访问  使用过滤器的形式配置请求地址的依赖权限
        // filterMap.put("/user/home","perms[user-home]");  //如果不具备指定权限,跳转到setUnauthorizedUrl指定的路径

        filterMap.put("/user/home", "roles[系统管理员]");    //具备某个角色才能访问
        filterMap.put("/user/**", "authc"); //当前请求地址认证后访问
        filterFactory.setFilterChainDefinitionMap(filterMap);
        return filterFactory;
    }


    //4.配置shiro注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

}

自定义公共异常处理器

package cn.itcast.shiro;

import org.apache.shiro.authz.AuthorizationException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义的公共异常处理器
 *      1.声明异常处理器
 *      2.对异常统一处理
 */
@ControllerAdvice
public class BaseExceptionHandler {

    @ExceptionHandler(value = AuthorizationException.class)
    @ResponseBody
    public String error(HttpServletRequest request, HttpServletResponse response,AuthorizationException e) {
		return "未授权";
    }
}

数据库
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

测试
在这里插入图片描述
在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!