java之路 —— Shiro与Springboot整合开发

这篇具有很好参考价值的文章主要介绍了java之路 —— Shiro与Springboot整合开发。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

java之路 —— Shiro与Springboot整合开发


前言

在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro。

在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro。

一、基本开发步骤

在整合之前,让我们先来了解一下Shiro开发的基本步骤:

1. 导入Shiro依赖:首先,在你的项目中添加Shiro的依赖,你可以通过Maven或者Gradle来管理项目依赖,确保你的项目中已经引入Shiro的相关库文件。

2. 配置Shiro: 接下来,你需要配置Shiro的一些核心组件,如安全管理器、认证器、授权器等。你可以在配置文件中添加相关的配置,或者在代码中进行编程式配置。

3. 编写和配置Realm: Realm是Shiro进行认证和授权的核心组件之一。你需要编写一个实现了Shiro提供的Realm接口的类,并根据你的业务需求,实现其中的认证和授权逻辑。在Shiro的配置中,将你的Realm配置为Shiro的认证和授权来源。

4. 设计登录和认证流程: 登录是Shiro应用中很重要的一部分。你可以设计一个登录界面,接受用户输入的用户名和密码,并将其传递给Shiro进行认证。在认证过程中,Shiro会调用你实现的Realm来验证用户的身份信息。

5. 设计和配置授权规则: 授权是Shiro应用中的另一个重要方面。你可以在Realm中定义角色和权限,并根据用户的身份和角色,来控制用户对应用中某些资源或操作的访问权限。在配置文件中,你可以设定哪些角色可以访问哪些资源。

6. 集成Shiro到你的应用: 你需要将Shiro集成到你的应用中,以便能够对用户进行认证和授权。可以通过编写过滤器、注解或者拦截器的方式,将Shiro应用到你的业务代码中。

7. 测试和调试: 在完成上述步骤后,你可以对应用进行测试和调试,确保Shiro在你的应用中正确地进行认证和授权。

8. 安全加固:最后,你可以进行一些额外的安全加固措施,如密码加密存储、登录日志记录等,以提高应用的安全性。

二、Springboot整合开发

java之路 —— Shiro与Springboot整合开发

1. 数据库设计

可以随意建设一个关系型数据库的多表,完成相应的一个属性值与关系映射。
权限设计通常采用RBAC即用户、角色、权限、用户-角色、角色-权限5张表。

2.前期准备

导入jar包,准备相应pom.xml

 <dependency>
	  <groupId>org.springframework.boot</groupId>
	  <artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	
	<dependency>
       <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring-boot-starter</artifactId>
        <version>1.7.1</version>
     </dependency>

        <dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>${mybatis-plus.version}</version>
		</dependency>
		
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<scope>runtime</scope>
	</dependency>
	
	<!--druid -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>${druid.version}</version>
		</dependency>

业务实现
可以通过通过Mybaits-plus或mybatis、Hibernate 查询用户的信息、用户角色信息、用户的权限信息。

@Service
@Transactional(rollbackFor=Exception.class)
public class UserServiceImpl implements UserService
{
    @Autowired
    private UserMapper userMapper;
    
    //查询用户信息
    @Override
    public User getUserByUserId(String userId)
    {
        Assert.notNull(userId, "userId不能为空");
        User user= userMapper.getUserByUserId(userId);
        
        if(user==null)
        {
            throw new UnknownAccountException("用户名或密码不正确");
        }
        
        //
        if("0".equals(user.getActive()))
        {
            throw new UnknownAccountException("用户状态不正确");
        }
        return user;
    }

   //获取用户角色
    @Override
    public List<Role> getRolesByUserOid(Integer userOid)
    {
        Assert.notNull(userOid, "userOid不能为空");
        return userMapper.getRolesByUserOid(userOid);
    }

   //获取用户权限
    @Override
    public List<Func> getResByRoleOid(Collection<Integer> roleOids)
    {
        Assert.notNull(roleOids, "roleOid不能为空");
        return userMapper.getResByRoleOid(roleOids);
    }
}


Dao层

public interface UserMapper extends BaseMapper<User>
{
    User getUserByUserId(String userId);
    
    List<Role> getRolesByUserOid(@Param("userOid")Integer userOid);
    
    List<Func> getResByRoleOid(@Param("roleOids")Collection<Integer> roleOids);
}

配置文件UserMapper.xml,并扫描对于该文件进行查找映射

<?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.skywares.fw.security.mapper.UserMapper">

<select id="getUserByUserId" resultType="com.skywares.fw.security.pojo.User">
      select 
        oid,
        userId,
        userName,
        active,
        gender,
        mobile,
        email,
        pwd        
      from fw_security_user u 
      where u.userId=#{userId}
 </select>
 
     <select id="getRolesByUserOid"  resultType="com.skywares.fw.security.pojo.Role">
        select 
		  r.oid,
		  r.roleId,
		  r.active,
		  r.updateUser,
		  r.updateDate
		from fw_security_user u 
		  join fw_security_user_role ur on ur.userOid = u.oid 
		  join fw_security_role r  on r.oid = ur.roleOid 
		 where u.active='1'
		   and u.oid =#{userOid}
    </select> 
    
      <select id="getResByRoleOid" resultType="com.skywares.fw.security.pojo.Func">
       select 
		  res.oid,
		  res.resId,
		  res.defaultLabel,
		  res.seq,
		  res.parentoid,
		  res.url,
		  res.exturl,
		  res.type,
		  res.active
        from  fw_security_res res 
		  join fw_security_role_res r on r.resOid = res.oid 
		  join fw_security_role role  on role.oid = r.roleOid 
		  where role.oid in
	         <foreach collection="roleOids" item="oid" open="(" close=")" separator=",">
	            #{oid}
	        </foreach>
		order BY res.oid desc
    </select>
</mapper>


三、Shiro的集成

自定义Realm实现认证

public class CustomerRealm extends AuthorizingRealm 
{
    @Autowired
    private UserService userService;
    
    //授权认证
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection)
    {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        User user = (User) principalCollection.getPrimaryPrincipal();
        Integer userOid=user.getOid();
        List<Role> roleList= userService.getRolesByUserOid(userOid);
        
        //用户角色
        Set<String> roleSet=new HashSet<>();
        //权限信息
        Set<String> funcSet=new HashSet<>();
        
        Set<Integer> roleOids=new HashSet<>();
        
        //查询角色
        if(roleList!=null && !roleList.isEmpty())
        {
            roleList.stream().forEach(t->{
                roleSet.add(String.valueOf(t.getRoleId()));
                roleOids.add(t.getOid());
            });
        }
        
        //查询权限
        List<Func> funcList= userService.getResByRoleOid(roleOids);
        if(funcList!=null && !funcList.isEmpty()){
            
            for(Func func:funcList)
            {
                funcSet.add(func.getUrl());
            }
        }
        
        //添加角色
        info.addRoles(roleSet);
        
        //添加权限
        info.addStringPermissions(funcSet);
        
        return info;
    }

    //用户认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authToken) throws AuthenticationException
    {        
        //采用用户名和密码方式
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authToken;
        String userId = usernamePasswordToken.getUsername();
        //密码
        String password = new String(usernamePasswordToken.getPassword());
        // 通过用户id获取用户信息
        User user = userService.getUserByUserId(userId);
        //认证。密码进行加密处理 
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPwd(),new CustByteSource(user.getUserId()),getName());
        return info;
    }
}


其中 doGetAuthenticationInfo:实现用户的认证,本文采用的是用户名和密码的方式。 doGetAuthorizationInfo :加载用户的授权信息 CustByteSource: 用户自定义的加密方式

可以自定义加密方式

public class CustByteSource implements ByteSource, Serializable
{
    private static final long serialVersionUID = -3818806283942882146L;
    private byte[] bytes;
    private String cachedHex;
    private String cachedBase64;

    public CustByteSource()
    {
    }

    public CustByteSource(byte[] bytes)
    {
        this.bytes = bytes;
    }

    public CustByteSource(char[] chars)
    {
        this.bytes = CodecSupport.toBytes(chars);
    }

    public CustByteSource(String string)
    {
        this.bytes = CodecSupport.toBytes(string);
    }

    public CustByteSource(ByteSource source)
    {
        this.bytes = source.getBytes();
    }

    public CustByteSource(File file)
    {
        this.bytes = new CustByteSource.BytesHelper().getBytes(file);
    }

    public CustByteSource(InputStream stream)
    {
        this.bytes = new CustByteSource.BytesHelper().getBytes(stream);
    }

    public static boolean isCompatible(Object o)
    {
        return o instanceof byte[] || o instanceof char[]
                || o instanceof String || o instanceof ByteSource
                || o instanceof File || o instanceof InputStream;
    }

    @Override
    public byte[] getBytes()
    {
        return this.bytes;
    }

    @Override
    public boolean isEmpty()
    {
        return this.bytes == null || this.bytes.length == 0;
    }

    @Override
    public String toHex()
    {
        if (this.cachedHex == null)
        {
            this.cachedHex = Hex.encodeToString(getBytes());
        }
        return this.cachedHex;
    }

    @Override
    public String toBase64()
    {
        if (this.cachedBase64 == null)
        {
            this.cachedBase64 = Base64.encodeToString(getBytes());
        }
        return this.cachedBase64;
    }

    @Override
    public String toString()
    {
        return toBase64();
    }

    @Override
    public int hashCode()
    {
        if (this.bytes == null || this.bytes.length == 0)
        {
            return 0;
        }
        return Arrays.hashCode(this.bytes);
    }

    @Override
    public boolean equals(Object o)
    {
        if (o == this)
        {
            return true;
        }
        if (o instanceof ByteSource)
        {
            ByteSource bs = (ByteSource) o;
            return Arrays.equals(getBytes(), bs.getBytes());
        }
        return false;
    }

    private static final class BytesHelper extends CodecSupport
    {
        /**
         * 嵌套类也需要提供无参构造器
         */
        private BytesHelper()
        {
        }

        public byte[] getBytes(File file)
        {
            return toBytes(file);
        }

        public byte[] getBytes(InputStream stream)
        {
            return toBytes(stream);
        }
    }
}

通过shiro提供加密方式针对密码进行加密处理,用户注册获取密码方式如下:

   public static final String md5Pwd(String salt,String pwd)
    {
        //加密方式
        String hashAlgorithmName = "MD5";
        //盐:为了即使相同的密码不同的盐加密后的结果也不同
        ByteSource byteSalt = ByteSource.Util.bytes(salt);
        //加密次数
        int hashIterations = 2;
        SimpleHash result = new SimpleHash(hashAlgorithmName, pwd, byteSalt, hashIterations);
        return result.toString();
    }

Shiro核心配置

@Configuration
public class ShiroConfig
{
   // 自定义密码加密规则
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher()
    {
        HashedCredentialsMatcher hashedCredentialsMatcher =new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(2);
        //true 代表Hex编码,fasle代表采用base64编码
        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        return hashedCredentialsMatcher;
    }
    
    // 自定义认证
    @Bean
    public CustomerRealm customerRealm()
    {
        CustomerRealm customerRealm=new  CustomerRealm();
        customerRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        customerRealm.setCachingEnabled(false);
        return customerRealm;
    }
    
    //需要定义DefaultWebSecurityManager,否则会报bean冲突
    @Bean
    public DefaultWebSecurityManager securityManager() 
    {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(customerRealm());
        securityManager.setRememberMeManager(null);
        return securityManager;
    }
    
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager)
    {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //给filter设置安全管理
        factoryBean.setSecurityManager(securityManager);
        
        //配置系统的受限资源
        Map<String,String> map = new HashMap<>();
        //登录请求无需认证
        map.put("/login", "anon");
        //其他请求需要认证
        map.put("/**", "authc");
        
        //访问需要认证的页面如果未登录会跳转到/login
        factoryBean.setLoginUrl("/login");
        //访问未授权页面会自动跳转到/unAuth
        factoryBean.setUnauthorizedUrl("/unAuth");
        factoryBean.setFilterChainDefinitionMap(map);
        return factoryBean;
    }
    
    
    /**
     * 开启注解方式,页面可以使用注解
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

四、测试

// 登录测试
@Controller
@RequestMapping("")
public class LoginController
{
   @RequestMapping("/login")
   @ResponseBody
   public String login(@RequestParam String userName,@RequestParam String password)
   {
     Subject subject = SecurityUtils.getSubject();
     UsernamePasswordToken usernamePasswordToken =new UsernamePasswordToken(userName, password);
     subject.login(usernamePasswordToken);
     return "成功";
   }
   
      /**
    * 用户未登录
    * @return
    */
   @RequestMapping("/unLogin")
   public String unLogin()
   {
     return "login.html";
   }
   
   /**
    * 用户未授权
    * @return
    */
   @RequestMapping("/unAuth")
   public String unAuth()
   {
     return "unAuth.html";
   }
}

// 角色和权限测试
@RestController
@RequestMapping("/app/sys/user")
public class UserController
{

   @RequestMapping("/list")
   @RequiresPermissions("/app/sys/user/list")
   public String list()
   {
       return "成功";
   }
   
   @RequestMapping("/roleTest")
   @RequiresRoles("admin1")
   public String roleTest()
   {
       return "成功";
   }
   
   @RequestMapping("/resourceTest")
   @RequiresPermissions("/app/sys/user/list1")
   public String resourceTest()
   {
       return "成功";
   }
}


这里就做一个授权测试看一下就行了

//访问需要认证的页面如果未登录会跳转到/login路由进行登陆
factoryBean.setLoginUrl("/unLogin");

用户访问/login请求输入正确的用户名和密码
java之路 —— Shiro与Springboot整合开发文章来源地址https://www.toymoban.com/news/detail-510022.html

到了这里,关于java之路 —— Shiro与Springboot整合开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • shiro 整合 spring 实战及源码详解

    前面我们学习了如下内容: 5 分钟入门 shiro 安全框架实战笔记 shiro 整合 spring 实战及源码详解 相信大家对于 shiro 已经有了最基本的认识,这一节我们一起来学习写如何将 shiro 与 spring 进行整合。 定义一个简单的服务类,用于演示 @RequiresPermissions 注解的权限校验。 我们对原

    2024年02月22日
    浏览(14)
  • springboot整合shiro+jwt+redis详解

    三大核心组件:Subject、SecurityManager、Realm Subject 主体,代表了当前 “用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 Subject,如网络爬虫,机器人等;即一个抽象概念;所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManag

    2023年04月09日
    浏览(18)
  • Shiro整合SpringBoot,实战下的应用场景

    整合springBoot+shiro流程: 环境准备 身份认证 2.1 密码加密 2.2 非法请求控制 授权,鉴权 项目目录: 认证框架五表设计: 准备 user用户表 、user_role用户角色关系表、 role角色表 、 role_permission角色权限关系表、 permission权限表 ; user用户表: user_role用户角色关系表: role角色表

    2024年02月09日
    浏览(15)
  • SpringBoot+Shiro框架整合实现前后端分离的权限管理基础Demo

    记录一下使用SpringBoot集成Shiro框架实现前后端分离Web项目的过程,后端使用SpringBoot整合Shiro,前端使用vue+elementUI,达到前后端使用token来进行交互的应用,这种方式通常叫做无状态,后端只需要使用Shiro框架根据前端传来的token信息授权访问相应资源。 案例源码:SpringBoot+Sh

    2024年02月06日
    浏览(16)
  • 3万字《SpringBoot微服务开发——Shiro(安全)》

    log4j.logger.org.apache.shiro.util.ThreadContext=WARN log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN shiro.ini ,需要安装ini插件 [users] root = secret, admin guest = guest, guest presidentskroob = 12345, president darkhelmet = ludicrousspeed, darklord, schwartz lonestarr = vespa, goodguy, schwartz [roles] admin = * schwartz = lightsaber:* go

    2024年04月18日
    浏览(18)
  • java springboot整合MyBatis-Plus 多用点Plus支持一下国人开发的东西吧

    文章java springboot整合MyBatis做数据库查询操作讲述了boot项目整合MyBatis的操作方法 但现在就还有一个 MyBatis-Plus Plus是国内整合的一个技术 国内的很多人会喜欢用 特别是一些中小型公司 他们用着会比较舒服 好 然后我们打开idea 创建一个项目 选择 Spring Initializr 工程 调一下项目

    2024年02月09日
    浏览(19)
  • 017-信息打点-语言框架&开发组件&FastJson&Shiro&Log4j&SpringBoot等

    1、CMS指纹识别-不出网程序识别 2、开发框架识别-PHPPythonJava 3、开发组件识别-Java常见安全漏洞组件 解决: 1、CMS识别到后期漏洞利用和代码审计 2、开发框架识别到后期漏洞利用和代码审计 3、开发组件识别到后期漏洞利用和代码审计 演示案例: ➢指纹识别-本地工具-GotoSc

    2024年01月21日
    浏览(18)
  • spring boot整合第三方微信开发工具 weixin-java-miniapp 实现小程序微信登录

    有时候项目需要用到微信登录或获取用户的手机号码,weixin-java-miniapp是一个好用的第三方工具,不用我们自己写httpcline调用。 导入jar包 添加一个resource.properties文件,写上小程序的appid和secret 添加两个配置文件 WxMaProperties.java WxMaConfiguration.java 如何使用 小程序给微信发送消息

    2024年02月16日
    浏览(11)
  • SSM+Shiro安全框架整合(完成安全认证--登录+权限授权)+ssm整合shiro前后端分离

    目录 1.搭建SSM框架  1.1.引入相关的依赖 1.2. spring配置文件 1.3. web.xml配置文件 1.4.配置Tomcat并启动 2.ssm整合shiro---认证功能  (1).引入依赖 (2).修改spring配置文件 (3).修改web.xml文件 (4).新建login.jsp(登录页面) (5).新建success.jsp(登录成功后跳转到此) (6).创建User实体类 (7).创建LoginVo

    2024年02月15日
    浏览(20)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包