Shiro安全框架集合(二)

目录

1、自定义Realm(单个Realm)

1.1编写实体类

1.2编写Mapper接口

1.3启动类加载Mapper接口

1.4 自定义Realm

 1.5将Realm放入SecurityMaanager中管理

2、自定义Realm(多个Realm认证)

 2.1编写实体类

 2.2创建mapper接口

2.3自定义Realm(多Realm)

2.4修改SecurityConfig配置类

2.5登录认证

3、多Realm认证策略

4、异常处理

 5、散列算法

6、加密认证

6.1数据

6.2修改自定义的Realm类

6.3在注册Realm中添加加密算法


1、自定义Realm(单个Realm)

1.1编写实体类

package com.example.shrio.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName(value = "users2")
public class Users {
    @TableId(value = "uid",type = IdType.AUTO)
    private Integer id;
    private String username;
    private String password;
}

1.2编写Mapper接口

package com.example.shrio.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.shrio.domain.Users;
import org.apache.ibatis.annotations.Mapper;


@Mapper
public interface UsersMapper extends BaseMapper<Users> {

}

1.3启动类加载Mapper接口

package com.example.shrio;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan
public class ShrioApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShrioApplication.class, args);
    }

}

1.4 自定义Realm

@component将MyRealm类实例化放入Spring容器中管理,相当于<bean id=“myRealm” class="" />

package com.example.shrio.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.shrio.domain.Users;
import com.example.shrio.mapper.UsersMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

//自定义Realm类
@Component
public class MyRealm extends AuthorizingRealm {

    @Resource
    private UsersMapper usersMapper;

    //自定义认证方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//        1、获取用户输入的用户名
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//        2、根据用户名查询用户
        QueryWrapper<Users> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("username",token.getUsername());
        Users users = usersMapper.selectOne(queryWrapper);
//        3、将查询到的用户封装成认证信息
        if(users==null){
            System.out.println("用户名不存在");
        }
        /**
         * 参数一: 用户
         * 参数二: 密码
         * 参数三: Realm名
         */
        return new SimpleAuthenticationInfo(users,users.getPassword(),"myRealm");
    }

    //自定义授权方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

}

 1.5将Realm放入SecurityMaanager中管理

package com.example.shrio.config;

import com.example.shrio.realm.MyRealm;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class ScurityConfig {

    //将SecurityManager交予容器管理
    @Bean
    public DefaultWebSecurityManager securityManager(MyRealm myRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//        securityManager.setRealm(jdbcRealm);
        securityManager.setRealm(myRealm);
        return securityManager;
    }
}

2、自定义Realm(多个Realm认证)

 2.1编写实体类

package com.example.shrio.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("admin")
public class Admin {
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    private String name;
    private String password;
}

 2.2创建mapper接口

package com.example.shrio.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.shrio.domain.Admin;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface AdminMapper extends BaseMapper<Admin> {
}

2.3自定义Realm(多Realm)

package com.example.shrio.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.shrio.domain.Users;
import com.example.shrio.mapper.UsersMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

//自定义Realm类
@Component
public class MyRealm extends AuthorizingRealm {

    @Resource
    private UsersMapper usersMapper;

    //自定义认证方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//        1、获取用户输入的用户名
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//        2、根据用户名查询用户
        QueryWrapper<Users> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("username",token.getUsername());
        Users users = usersMapper.selectOne(queryWrapper);
//        3、将查询到的用户封装成认证信息
        if(users==null){
            System.out.println("用户名不存在");
        }
        /**
         * 参数一: 用户
         * 参数二: 密码
         * 参数三: Realm名
         */
        return new SimpleAuthenticationInfo(users,users.getPassword(),"myRealm");
    }

    //自定义授权方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

}
package com.example.shrio.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.shrio.domain.Admin;
import com.example.shrio.mapper.AdminMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component(value = "myRealm2")
public class MyRealm2  extends AuthorizingRealm {

    @Resource
    private AdminMapper adminMapper;

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        QueryWrapper<Admin> wrapper = new QueryWrapper<Admin>().eq("name", username);
        Admin admin = adminMapper.selectOne(wrapper);
        if(admin==null){
            System.out.println("admin不存在");
        }

        return new SimpleAuthenticationInfo(admin,admin.getPassword(),"myRealm2");
    }

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }


}

2.4修改SecurityConfig配置类

    //将SecurityManager交予容器管理
    @Bean
    public DefaultWebSecurityManager securityManager(MyRealm myRealm, MyRealm2 myRealm2){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        List<Realm> list=new ArrayList<>();
        list.add(myRealm);
        list.add(myRealm2);
        securityManager.setRealms(list);
        return securityManager;
    }

2.5登录认证

controller层:

    @PostMapping("/login3")
    public String login3(String username,String password){
        return loginService.login3(username,password);
    }

service层:

package com.example.shrio.service;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sql.DataSource;

@Service
public class LoginService {

    @Resource
    private DefaultWebSecurityManager securityManager;

    /**
     * 将Shiro交予容器管理
     * @param username
     * @param password
     * @return
     */
    public String login3(String username,String password){
//        1、将SecurityManager添加到运行环境中
        SecurityUtils.setSecurityManager(securityManager);
//        2、获取Subject对象
        Subject subject = SecurityUtils.getSubject();
//        3、将前端传过来的用户名和密码封装成Shiro对象
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//        4、shiro认证
        try{
            subject.login(token);
//        5、认证通过
           return "main";
        }catch (AuthenticationException exception){
//        6、认证失败
            return "fail";
        }
    }
}

3、多Realm认证策略

       如果有多个Realm,怎样才能认证成功,这就是认证策略。认证策略主要使用的是 AuthenticationStrategy接口,这个接口有三个实现类

策略意义
AtLeastOneSuccessfulStrategy(默认)只要有一个Realm验证成功即可,返回所有成功的认证信息
FirstSuccessfulStrategy只要有一个Realm验证成功即可只返回第一个成功的认证信息,其他的忽略
AllSuccessfulStrategy所有Realm验证成功才算成功,如果有一个失败则认证失败
//   认证策略
    @Bean
    public ModularRealmAuthenticator modularRealmAuthenticator(){
//      设置认证策略
        ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
//      默认认证策略(一个登录成功则成功)
//        authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
//      第一个成功则成功
//        authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
//      全部认证成功则成功
        authenticator.setAuthenticationStrategy(new AllSuccessfulStrategy());
        return authenticator;
    }


//将SecurityManager交予容器管理
    @Bean
    public DefaultWebSecurityManager securityManager(MyRealm myRealm, MyRealm2 myRealm2){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//        securityManager.setRealm(jdbcRealm);
//        securityManager.setRealm(myRealm);
        securityManager.setAuthenticator(modularRealmAuthenticator());
        List<Realm> list=new ArrayList<>();
        list.add(myRealm);
        list.add(myRealm2);
        securityManager.setRealms(list);
        return securityManager;
    }

4、异常处理

当Shiro认证失败后,会抛出AuthorizationException异常。该异常的子类分别代表不同的认证失败原因,我们可以通过捕捉它们确定认证失败原因。

  • DisabledAccountException:账户失效
  • ConcurrentAccessException:竞争次数过多
  • ExcessiveAttemptsException:尝试次数过多
  • UnknownAccountException:用户名不正确
  • IncorrectCredentialsException:凭证(密码)不正确
  • ExpiredCredentialsException:凭证过期

 5、散列算法

散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,适合于对密码进行加密。比如密码admin,产生的散列值是21232f297a57a5a743894a0e4a801fc3,但在md5解密网站很容易的通过散列值得到密码admin所以在加密时我们可以加一些只有系统知道的干扰数据,这些干扰数据称之为“盐”,并且可以进行多次加密,这样生成的散列值相对来说更难破解。Shiro支持的散列算法:Md2Hash、Md5Hash、Sha1Hash、Sha256Hash、Sha384Hash、Sha512Hash

package com.example.shrio;

import org.apache.shiro.crypto.hash.Md5Hash;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class ShiroTestMain {

    @Test
    public void tst1(){
        /**
         * 参数一 加密密码
         * 参数二 盐
         * 参数三 加密次数
         */
        Md5Hash result=new Md5Hash("admin");
        System.out.println(result);

        Md5Hash result2=new Md5Hash("admin","sxt");
        System.out.println(result2);

        Md5Hash result3 = new Md5Hash("admin123", "sxt", 5);
        System.out.println(result3);
    }
}

6、加密认证

6.1数据

 6.2修改自定义的Realm类

package com.example.shrio.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.shrio.domain.Admin;
import com.example.shrio.mapper.AdminMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component(value = "myRealm2")
public class MyRealm2  extends AuthorizingRealm {

    @Resource
    private AdminMapper adminMapper;

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        QueryWrapper<Admin> wrapper = new QueryWrapper<Admin>().eq("name", username);
        Admin admin = adminMapper.selectOne(wrapper);
        if(admin==null){
            System.out.println("admin不存在");
        }
        /**
         * 参数一: 用户
         * 参数二: 密码
         * 参数三: 盐
         * 参数四: Realm名
         */
        return new SimpleAuthenticationInfo(admin,
                admin.getPassword(),
                ByteSource.Util.bytes(admin.getSalt()),
                "myRealm2");
    }

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }


}

6.3在注册Realm中添加加密算法

    //配置加密算法
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");
        matcher.setHashIterations(5);
        return matcher;
    }

    //将SecurityManager交予容器管理
    @Bean
    public DefaultWebSecurityManager securityManager(MyRealm2 myRealm2){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        myRealm2.setCredentialsMatcher(hashedCredentialsMatcher());
        securityManager.setRealm(myRealm2);
        return securityManager;
    }

 孤独&烙印的博客_CSDN博客-springSecurity,docker,spring-fox领域博主

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ShiroApache 软件基金会的一个开源安全框架,提供了一整套安全管理的解决方案,包括认证、授权、加密和会话管理等功能。Shiro 的目标在于提供简单易用的 API,同时支持高度定制化的需求。 Spring Boot 是一个快速开发的框架,它可以帮助我们快速搭建一个基于 Spring 的应用程序。Spring Boot 的优势在于它内置了很多常用的依赖库和配置,使得开发者可以更加专注于业务逻辑的实现,而不用过多关注底层的配置。 集成 ShiroSpring Boot 可以为我们的应用程序提供强大的安全管理功能,并且可以快速实现这些功能。下面我们将介绍如何在 Spring Boot 中集成 Shiro。 1. 引入 Shiro 依赖 在 pom.xml 文件中添加以下依赖: ``` <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.2</version> </dependency> ``` 这个依赖包含了 Shiro 的核心库以及与 Spring 集成的库。 2. 配置 ShiroSpring Boot 中,我们可以通过在 application.properties 或 application.yml 文件中配置 Shiro。以下是一个示例的 YAML 配置文件: ``` server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/db?useSSL=false&serverTimezone=UTC username: root password: root shiro: loginUrl: /login successUrl: /index filterChainDefinitions: /index = authc ``` 其中 loginUrl 指定了登录页面的 URL,successUrl 指定了登录成功后跳转的 URL,filterChainDefinitions 指定了 URL 的过滤规则。 3. 编写 Shiro 相关代码 在 Spring Boot 中,我们可以使用 Shiro 的注解来实现对方法或 URL 的权限控制。以下是一个示例代码: ``` @RestController @RequestMapping("/api") public class UserController { @RequiresAuthentication @GetMapping("/user/{id}") public User getUser(@PathVariable Long id) { // ... } @RequiresPermissions("user:create") @PostMapping("/user") public void createUser(@RequestBody User user) { // ... } @RequiresRoles("admin") @DeleteMapping("/user/{id}") public void deleteUser(@PathVariable Long id) { // ... } } ``` 在上面的代码中,@RequiresAuthentication 表示需要认证才能访问该方法,@RequiresPermissions("user:create") 表示需要拥有 user:create 权限才能访问该方法,@RequiresRoles("admin") 表示需要拥有 admin 角色才能访问该方法。 4. 启动应用程序 现在我们可以启动应用程序并访问相应的 URL。如果当前用户没有足够的权限访问某个 URL,Shiro 会自动跳转到登录页面,并在登录成功后重定向到相应的 URL。 总结 通过集成 ShiroSpring Boot,我们可以快速构建一个安全的应用程序。在实际开发中,我们可以根据实际需求来配置 Shiro,例如使用自定义的 Realm、加密算法等。通过合理的配置和使用,我们可以提高应用程序的安全性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独&烙印

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值