SpringBoot集成Shiro

Posted cppdy

tags:

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

Shiro是一个安全框架,控制登陆,角色权限管理(身份认证、授权、回话管理、加密)

Shiro不会去维护用户,维护权限;这些需要通过realm让开发人员自己注入

1、在pom.xml中引入shiro的jar包

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

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.4.0</version>
</dependency>

2、在srcmain esources下创建ehcache-shiro.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="cacheManagerConfigFile">
    <defaultCache maxElementsInMemory="1000"
    eternal="false"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    overflowToDisk="false"
    diskPersistent="false"
    diskExpiryThreadIntervalSeconds="120"
    memoryStoreEvictionPolicy="LRU"/>
    <cache name="shiro-activeSessionCache"
    eternal="false"
    maxElementsInMemory="10000"
    overflowToDisk="false"
    timeToIdleSeconds="0"
    timeToLiveSeconds="0"/>
</ehcache>

3、创建User类

package com.cppdy.entity;

public class User {

    private int id;
    private String username;
    private String password;
    private int roleid;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getRoleid() {
        return roleid;
    }

    public void setRoleid(int roleid) {
        this.roleid = roleid;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

4、创建Role类

package com.cppdy.entity;

public class Role {

    private int id;
    private String rolename;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getRolename() {
        return rolename;
    }

    public void setRolename(String rolename) {
        this.rolename = rolename;
    }

}

5、创建Permission类

package com.cppdy.entity;

public class Permission {

    private int id;
    private String pername;
    private int roleid;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPername() {
        return pername;
    }

    public void setPername(String pername) {
        this.pername = pername;
    }

    public int getRoleid() {
        return roleid;
    }

    public void setRoleid(int roleid) {
        this.roleid = roleid;
    }

}

6、创建UserMapper接口

package com.cppdy.mapper;

import org.apache.ibatis.annotations.Mapper;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.cppdy.entity.User;

@Mapper
public interface UserMapper extends BaseMapper<User>{

}

7、创建RoleMapper接口

package com.cppdy.mapper;

import org.apache.ibatis.annotations.Mapper;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.cppdy.entity.Role;

@Mapper
public interface RoleMapper extends BaseMapper<Role>{

}

8、创建PermissionMapper接口

package com.cppdy.mapper;

import org.apache.ibatis.annotations.Mapper;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.cppdy.entity.Permission;

@Mapper
public interface PermissionMapper extends BaseMapper<Permission>{

}

9、创建UserService接口

package com.cppdy.service;

import com.cppdy.entity.User;

public interface UserService {

    public void update(String username, int id);

    public User selectUserByUsername(String username);

}

10、创建UserServiceImpl接口实现类

package com.cppdy.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.cppdy.entity.User;
import com.cppdy.mapper.UserMapper;
import com.cppdy.service.UserService;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    // 开启事务管理
    @Transactional
    public void update(String username, int id) {

        User user = userMapper.selectById(id);
        user.setUsername(username);
        // 更新一条数据
        userMapper.updateById(user);

    }

    @Override
    public User selectUserByUsername(String username) {
        Wrapper<User> wrapper = new EntityWrapper<>();
        wrapper.eq("username", username);
        List<User> list = userMapper.selectList(wrapper);
        if(list.size()>0) {
            return list.get(0);
        }
        return null;
    }

}

11、创建UserRealm类

package com.cppdy.realm;

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

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;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.cppdy.entity.Permission;
import com.cppdy.entity.Role;
import com.cppdy.entity.User;
import com.cppdy.mapper.PermissionMapper;
import com.cppdy.mapper.RoleMapper;
import com.cppdy.service.UserService;

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private PermissionMapper permissionMapper;

    // 控制角色权限
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        String username = (String) principals.getPrimaryPrincipal();
        // 将当前用户的角色和权限查询进来
        User user = userService.selectUserByUsername(username);
        Role role = roleMapper.selectById(user.getRoleid());

        info.addRole(role.getRolename());

        Wrapper<Permission> wrapper = new EntityWrapper<>();
        wrapper.eq("roleid", role.getId());
        List<Permission> selectList = permissionMapper.selectList(wrapper);
        ArrayList<String> perList = new ArrayList<String>();
        selectList.forEach(per -> {
            perList.add(per.getPername());
        });

        info.addStringPermissions(perList);
        return info;
    }

    // 控制登陆
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        AuthenticationInfo info = null;
        String username = (String) token.getPrincipal();
        User user = userService.selectUserByUsername(username);
        if (user != null) {
            info = new SimpleAuthenticationInfo(username, user.getPassword(), "cppdy");
        }
        return info;
    }

}

12、创建ShiroConfiguration配置类

package com.cppdy.config;

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

import javax.servlet.Filter;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.cppdy.realm.UserRealm;

@Configuration
public class ShiroConfiguration {
    
    @Bean
    public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //必须设置SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //拦截器
        Map<String,String> filterChainDefinitionMap=new LinkedHashMap<String,String>();
        //配置静态资源允许访问
        filterChainDefinitionMap.put("/user/login", "anon");
        filterChainDefinitionMap.put("/user/loginAction", "anon");
        //authc:所有url都必须认证通过才可以访问;anon:所有url都可以匿名访问
        filterChainDefinitionMap.put("/**", "authc");
        //如果不设置默认会自动寻找web工程跟目标下的/login.jsp页面
        shiroFilterFactoryBean.setLoginUrl("/user/login");
        //未授权界面
//        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        Map<String,Filter> filters=new HashMap<String,Filter>();
        shiroFilterFactoryBean.setFilters(filters);
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        
        return shiroFilterFactoryBean;
    }
    
    @Bean
    public EhCacheManager getEhCacheManager() {
        EhCacheManager em=new EhCacheManager();
        em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
        return em;
    }
    
    //开启Controller中的shiro注解
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap=new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }
    
    @Bean
    public DefaultWebSessionManager getDefaultWebSessionManager() {
        DefaultWebSessionManager defaultWebSessionManager=new DefaultWebSessionManager();
        defaultWebSessionManager.setSessionDAO(getMemorySessionDAO());
        defaultWebSessionManager.setGlobalSessionTimeout(4200000);
        defaultWebSessionManager.setSessionValidationSchedulerEnabled(true);
        defaultWebSessionManager.setSessionIdCookieEnabled(true);
        defaultWebSessionManager.setSessionIdCookie(getSimpleCookie());
        return defaultWebSessionManager;
    }
    
    @Bean
    public MemorySessionDAO getMemorySessionDAO() {
        MemorySessionDAO memorySessionDAO=new MemorySessionDAO();
        memorySessionDAO.setSessionIdGenerator(javaUuidSessionIdGenerator());
        return memorySessionDAO;
    }
    
    @Bean
    public JavaUuidSessionIdGenerator javaUuidSessionIdGenerator() {
        
        return new JavaUuidSessionIdGenerator();
    }
    
    /**
     * session自定义cookie名
     * @return
     */
    @Bean
    public SimpleCookie getSimpleCookie() {
        SimpleCookie simpleCookie=new SimpleCookie();
        simpleCookie.setName("security.session");
        simpleCookie.setPath("/");
        return simpleCookie;
    }
    
    @Bean
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        
        return new LifecycleBeanPostProcessor();
    }
    
    @Bean(name="securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm) {
        DefaultWebSecurityManager dwsm=new DefaultWebSecurityManager();
        dwsm.setRealm(userRealm);
        //用户授权/认证信息Cache,采用EhCache缓存
        dwsm.setCacheManager(getEhCacheManager());
        dwsm.setSessionManager(getDefaultWebSessionManager());
        return dwsm;
    }
    
    @Bean
    public UserRealm userRealm(EhCacheManager cacheManager) {
        UserRealm userRealm=new UserRealm();
        userRealm.setCacheManager(cacheManager);
        return userRealm;
    }
    
    /**
     * 开启shiro注解支持
     * @param userRealm
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(UserRealm userRealm) {
        AuthorizationAttributeSourceAdvisor aasa=new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(getDefaultWebSecurityManager(userRealm));
        return aasa;
    }
}

13、创建UserController类

package com.cppdy.controller;

import org.apache.ibatis.session.RowBounds;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
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.RestController;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.cppdy.entity.User;
import com.cppdy.mapper.UserMapper;

@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @RequestMapping("getUserById")
    public Object getUserById(int id) {

        return userMapper.selectById(id);
    }

    @RequiresPermissions("sys:delete")
    @RequestMapping("deleteUserById")
    public Object deleteUserById(int id) {

        return userMapper.deleteById(id);
    }

    @RequiresRoles("admin")
    @RequestMapping("getUser")
    public Object getUser() {
        // 适配器
        Wrapper<User> wrapper = new EntityWrapper<>();
        wrapper.like("username", "测试");
        // 倒序
        wrapper.orderBy("id", false);
        return userMapper.selectList(wrapper);
    }

    @RequestMapping("selectPage")
    public Object selectPage(int pageNum, int pageSize) {
        // 适配器
        Wrapper<User> wrapper = new EntityWrapper<>();

        RowBounds rowBounds = new RowBounds((pageNum - 1) * pageSize, pageSize);

        return userMapper.selectPage(rowBounds, wrapper);
    }

    @RequestMapping("login")
    public String login() {

        return "loginPage";
    }

    @RequestMapping("loginAction")
    public String loginAction(String username,String password) {
        Subject subject = SecurityUtils.getSubject();
        String md5 = new Md5Hash(password, "cppdy").toString();
        AuthenticationToken token = new UsernamePasswordToken(username, md5);
        try {
            // 如果执行subject.login抛出异常,则证明登陆成功
            subject.login(token);
            return "login success";
        } catch (AuthenticationException e) {
            // 有异常则证明登陆错误
            e.printStackTrace();
            return "login failed";
        }
    }

}

14、创建表(user、role、permission),并添加测试数据(password为:123456;md5加密后的password为:9faea48dae4030f38bcd1ae6a4f7fc01)

技术分享图片

 

技术分享图片

 

技术分享图片

 15、访问loginAction方法进行登录,再分别调用getUser和deleteUserById方法测试角色权限控制

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

springboot 后台框架平台 mybatis 集成代码生成器 shiro 权限 websocket

Springboot vue.js html 跨域 前后分离 shiro权限 集成代码生成器

Springboot学习Shiro快速入门及与SpringBoot集成

Springboot vue 前后分离 跨域 Activiti6 工作流 集成代码生成器 shiro权限

springboot集成shiro集成mybatis-plusredisquartz定时任务

SpringBoot学习- 8整合Shiro