2023-05-14 Shiro整合springboot

一、流程图

ShiroFilter会拦截用户发来的所有请求,然后判断该请求是否需要做认证和授权,也就是判断该请求访问的是受限资源还是公共资源,访问受限资源的话就要做认证和授权,利用SecurityManager、Realm做认证、授权,认证失败跳转到登录页,访问公共资源的话直接放行


image

二、shiro中的过滤器

image

三、整合步骤

1.引入shiro依赖

<dependency>

    <groupId>org.apache.shiro</groupId>

    <artifactId>shiro-spring-boot-starter</artifactId>

    <version>1.5.3</version>

</dependency>

2.创建自定义Realm类

这里面完成认证和授权相关业务

package com.szhedu.springboot_shiro.shiro.realms;

import com.szhedu.springboot_shiro.mapper.UserMapper;
import com.szhedu.springboot_shiro.pojo.User;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Objects;

/**
 * 自定义的realm
 */
public class CustomerRealm extends AuthorizingRealm {
    @Autowired
    private UserMapper userMapper;
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addRole("admin");
        authorizationInfo.addStringPermission("user:add:*");
        return authorizationInfo;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String principal = (String) authenticationToken.getPrincipal();
        //查询数据库,如果用户名和密码都校验成功,则认证通过
        User user = userMapper.getUser(principal);
        if(!Objects.isNull(user)){
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    principal,
                    user.getPassword(),
                    //盐
                    ByteSource.Util.bytes(user.getSalt()),
                    this.getName());
            return authenticationInfo;
        }
        return null;
    }
}

3.编写shiro配置类,包含三步①创建ShiroFilter②创建全局安全管理器③创建自定义Realm

package com.szhedu.springboot_shiro.config;

import com.szhedu.springboot_shiro.shiro.realms.CustomerRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
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;

/**
 * shiro配置类
 */
@Configuration
public class ShiroConfig {
    //1.创建ShiroFilter
    @Bean
    public ShiroFilterFactoryBean getShiroFilter(DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        //todo 1. 将全局安全管理器注入
        shiroFilter.setSecurityManager(defaultWebSecurityManager);
        //todo 2.设置受限资源
        Map<String, String> map = new HashMap<>();
        //公共资源先放开
        map.put("/user/login","anon");
        map.put("/user/register","anon");
        map.put("/register.jsp","anon");
        //authc表示这个资源需要认证和授权,如果没认证成功默认回到login.jsp
        map.put("/**","authc");
        shiroFilter.setFilterChainDefinitionMap(map);
        return shiroFilter;
    }
    //2.创建全局安全管理器
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //将自定义的realm设置到全局安全管理器中
        defaultWebSecurityManager.setRealm(realm);
        return defaultWebSecurityManager;
    }
    //3.创建自定义Realm
    @Bean
    public Realm getRealm(){
        CustomerRealm customerRealm = new CustomerRealm();
        //todo 修改凭证校验匹配器
        //这里,就会先对用户输入的密码进行MD5加密,然后再用加密后的密码去和数据库中的密码做equals判断
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //使用的算法
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //散列的次数
        hashedCredentialsMatcher.setHashIterations(1024);
        customerRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return customerRealm;
    }
}

4.登录接口(认证)

  //登录
    @PostMapping("/user/login")
    public String login(String username,String password){
        Subject subject = SecurityUtils.getSubject();
        try {
            //会调用我们自定义的realm类进行认证和授权
            subject.login(new UsernamePasswordToken(username,password));
            return "redirect:/index.jsp";
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误");
        }
        return "redirect:/login.jsp";
    }

5.授权:从数据库查询登陆用户的角色信息和所具有的权限信息,封装到SimpleAuthorizationInfo对象中返回

 //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
        List<Role> roles = userMapper.getRoles(primaryPrincipal);
        if (roles != null){
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            roles.stream().forEach(
                    role -> {
                        //封装角色信息
                        authorizationInfo.addRole(role.getName());
                        //封装权限信息
                        List<Perms> perms = userMapper.getPerms(role.getId());
                        perms.forEach(
                                perm -> {
                                    authorizationInfo.addStringPermission(perm.getName());
                                }
                        );
                    }
            );
            return authorizationInfo;
        }
        return null;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。