Springboot整合Shiro

目录

1.springboot整合shiro-----认证(登录)

1.1.创建springboot项目

1.2.引依赖

1.3.修改application配置文件

1.4.创建实体类

1.5.创建dao层

1.6.创建service层

1.7.编写realm

1.8.创建vo层

1.9.创建Controller层

1.10. 创建shiro的配置类

1.11.创建登录页面与登录成功页面

1.12.测试

2.springboot整合shiro--授权(权限)

2.1.修改Realm

2.2.创建Service

2.3.创建PermissionDao 

2.4.创建PermissionDao.xml

2.5.创建UserController

2.6.修改登录成功页面

2.7.添加依赖

2.8.ShiroConfig修改

测试

 2.9.权限不足时跳转到一个页面

3.springboot整合shiro----前后端分离

创建Result 

3.1.登录成功或失败---返回json数据

3.2.权限不足时---返回json数据

3.3.未登录时---返回json数据

 4.shiro权限对象缓存到redis中

5.使用Swagger2接口文档测试


1.springboot整合shiro-----认证(登录)

1.1.创建springboot项目

Springboot整合Shiro_第1张图片

1.2.引依赖


        
            org.springframework.boot
            spring-boot-starter-web
        

        
            mysql
            mysql-connector-java
        

        
            com.baomidou
            mybatis-plus-boot-starter
            3.5.1
        
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        
        
            org.projectlombok
            lombok
        
    
        
            org.apache.shiro
            shiro-spring-boot-starter
            1.7.0
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

1.3.修改application配置文件

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///shiro?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456789

#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

mybatis-plus.mapper-locations=classpath:/mapper/*.xml

#thymeleaf的视图解析器
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
#定义shiro的加密算法
shiro.hashAlgorithmName=MD5
shiro.hashIterations=1024

1.4.创建实体类

@Data
public class Permission {
    @TableId(type = IdType.AUTO)
    private Integer perid;
    private String pername;
    private String percode;
}
@Data
public class User implements Serializable {

    @TableId(type = IdType.AUTO)
    private Integer userid;
    private String username;
    private String userpwd;
    private String sex;
    private String address;
    private String salt;
}

1.5.创建dao层

public interface UserDao extends BaseMapper {
}

开启扫描dao包

Springboot整合Shiro_第2张图片

1.6.创建service层

public interface UserService {
    public User findByUsername(String username);
}



@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public User findByUsername(String username) {
        // 创建一个查询条件包装器
        QueryWrapper wrapper = new QueryWrapper<>();

        // 设置查询条件为"username = username"
        wrapper.eq("username", username);

        // 使用查询条件执行查询操作,返回单个用户对象
        User user = userDao.selectOne(wrapper);
        return user;
    }
}

1.7.编写realm

public class MyRealm extends AuthorizingRealm {

    @Autowired
    protected UserService userService;

    // 授权--权限
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 在此处添加授权逻辑
        return null;
    }

    //认证 -- 登录
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 1. 获取登录账号
        String username = token.getPrincipal().toString();

        // 2. 根据账号获取用户信息
        User user = userService.findByUsername(username);
        if (user != null) {
            // 使用用户的盐值创建 ByteSource 对象
            ByteSource salt = ByteSource.Util.bytes(user.getSalt());

            // 创建 SimpleAuthenticationInfo 对象,包含用户信息、密码、盐值和 Realm 名称
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getUserpwd(), salt, this.getName());
            return info;
        }
        // 用户不存在,返回 null
        return null;
    }
}

1.8.创建vo层

@Data
public class LoginVo {
    private String Password;
    private String Username;
}

1.9.创建Controller层

@Controller
public class LoginController {

    @PostMapping("/login")
    public String login(LoginVo loginVo) {
        // 获取当前主体对象
        Subject subject = SecurityUtils.getSubject();

        // 创建用户名密码令牌
        UsernamePasswordToken token = new UsernamePasswordToken(loginVo.getUsername(), loginVo.getPassword());

        try {
            // 调用主体的登录方法进行认证
            subject.login(token);

            // 登录成功,返回成功标识
            return "success";
        } catch (Exception e) {
            e.printStackTrace();

            // 登录失败,重定向到登录页面
            return "redirect:/login.html";
        }
    }

}

1.10. 创建shiro的配置类

----(相当于ssm中的spring配置文件)

package com.wqg.config;

import com.wqg.realm.MyRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

/**
 * @ fileName:ShiroConfig
 * @ description:
 * @ author:wqg
 * @ createTime:2023/7/7 16:33
 */
@Configuration
public class ShiroConfig {

    @Bean
    public DefaultWebSecurityManager securityManager() {
        // 创建默认的 Web 安全管理器
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置安全管理器使用的 Realm
        securityManager.setRealm(myRealm());
        // 返回安全管理器
        return securityManager;
    }

    @Bean
    public MyRealm myRealm(){
        MyRealm myRealm=new MyRealm();
        //设置密码加密器
        myRealm.setCredentialsMatcher(credentialsMatcher());
        return myRealm;
    }

    @Value("${shiro.hashAlgorithmName}")
    private String hashAlgorithmName;
    @Value("${shiro.hashIterations}")
    private int hashIterations;
    @Bean
    public HashedCredentialsMatcher credentialsMatcher() {
        // 创建密码匹配器对象
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();

        // 设置密码算法名称
        credentialsMatcher.setHashAlgorithmName(hashAlgorithmName);

        // 设置哈希迭代次数
        credentialsMatcher.setHashIterations(hashIterations);

        // 返回密码匹配器对象
        return credentialsMatcher;
    }


    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean factoryBean() {
        // 创建 Shiro 过滤器工厂 Bean
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager());

        // 设置登录页面的 URL
        shiroFilterFactoryBean.setLoginUrl("/login.html");

        // 设置过滤规则
        Map map = new HashMap<>();
        // 指定 /login URL 不需要进行认证
        map.put("/login", "anon");
        // 其他 URL 需要进行认证
        map.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        // 返回 Shiro 过滤器工厂 Bean
        return shiroFilterFactoryBean;
    }


    //springboot如何注册web三大组件。
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        // 创建过滤器注册Bean对象
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>();

        // 设置过滤器为DelegatingFilterProxy
        filterRegistrationBean.setFilter(new DelegatingFilterProxy());

        // 设置过滤器名称
        filterRegistrationBean.setName("shiroFilter");

        // 添加过滤器的URL模式,匹配所有URL
        filterRegistrationBean.addUrlPatterns("/*");

        // 返回过滤器注册Bean对象
        return filterRegistrationBean;
    }

}

1.11.创建登录页面与登录成功页面

Springboot整合Shiro_第3张图片




    
    登录


姓名:

密码:




    
    Title


登录成功~~~

1.12.测试

Springboot整合Shiro_第4张图片

2.springboot整合shiro--授权(权限)

2.1.修改Realm

    @Autowired
    protected PermissionService permissionService;

    // 授权--权限
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 获取主体中的用户对象
        User user = (User) principals.getPrimaryPrincipal();

        // 根据用户ID查询用户权限列表
        List list = permissionService.selectPermissionByUserid(user.getUserid());

        // 如果权限列表不为空
        if (list.size() != 0) {
            // 创建 SimpleAuthorizationInfo 对象
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

            // 将权限列表添加到授权信息中
            info.addStringPermissions(list);

            // 返回授权信息
            return info;
        }
        // 返回空,表示无授权信息
        return null;
    }

2.2.创建Service

public interface PermissionService {
    public List selectPermissionByUserid(Integer userid);
}
@Service
public class PermissionServiceImpl implements PermissionService {
    @Autowired
    private PermissionDao permissionDao;

    @Override
    public List selectPermissionByUserid(Integer userid) {
        // 根据用户ID查询用户权限列表
        List permissionList = permissionDao.findPermissionByUserid(userid);

        // 使用流操作将权限列表中的每个权限对象映射为权限编码,并收集为新的列表
        List collect = permissionList.stream().map(Permission::getPercode).collect(Collectors.toList());

        // 返回权限编码列表
        return collect;
    }

}

2.3.创建PermissionDao 

@Mapper
public interface PermissionDao extends BaseMapper {
    List findPermissionByUserid(Integer userid);
}

2.4.创建PermissionDao.xml





    

2.5.创建UserController

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

    @GetMapping("/query")
    @RequiresPermissions(value = {"user:query","user:delete"},logical = Logical.OR) //可以通过多个路径访问内部资源
    //@RequiresPermissions(value = "user:query")
    public String query(){
        return "user:query------------------------";
    }

    @GetMapping("/update")
    @RequiresPermissions(value = "user:update")
    public String update(){
        return "user:update------------------------";
    }

    @GetMapping("/delete")
    @RequiresPermissions(value = "user:delete")
    public String delete(){
        return "user:delete------------------------";
    }

    @GetMapping("/insert")
    @RequiresPermissions(value = "user:insert")
    public String insert(){
        return "user:insert------------------------";
    }

    @GetMapping("/export")
    @RequiresPermissions(value = "user:export") //该注解不能被识别
    public String export(){
        return "user:export------------------------";
    }
}

2.6.修改登录成功页面




    
    Title


登录成功~~~

2.7.添加依赖


        
            com.github.theborakompanioni
            thymeleaf-extras-shiro
            2.0.0
        

2.8.ShiroConfig修改

 /**
     * 这里是为了能在html页面引用shiro标签,
     */ 
 @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {
        // 创建 Shiro 方言对象,用于在 Thymeleaf 中集成 Shiro 标签
        return new ShiroDialect();
    }

测试

Springboot整合Shiro_第5张图片

 2.9.权限不足时跳转到一个页面

未跳转:

Springboot整合Shiro_第6张图片

 实现跳转:

创建MyExceptionHandler

@ControllerAdvice
@Slf4j
public class MyExceptionHandler {

    @ExceptionHandler(value = AuthorizationException.class)
    public String authorizationException(Exception e){
        log.error("异常的内容====="+e.getMessage());
        return "403" ;
    }

}

创建403.html




    
    Title


权限不足~~~~

测试

Springboot整合Shiro_第7张图片

3.springboot整合shiro----前后端分离

创建Result 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
    private Integer code;
    private String msg;
    private Object data;
}

3.1.登录成功或失败---返回json数据

 修改LoginController

Springboot整合Shiro_第8张图片

测试:

Springboot整合Shiro_第9张图片

3.2.权限不足时---返回json数据

修改MyExceptionHandler

Springboot整合Shiro_第10张图片

测试

Springboot整合Shiro_第11张图片

3.3.未登录时---返回json数据

添加依赖


        
            com.alibaba
            fastjson
            1.2.83
        

创建LoginFilter

public class LoginFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        //设置响应的内容类型为JSON,并使用UTF-8编码
        response.setContentType("application/json;charset=utf-8");

        // 获取用于写入响应的PrintWriter对象
        PrintWriter writer = response.getWriter();

        // 创建一个Result对象,包含401状态码和提示信息
        Result result = new Result(401, "请先登录---", null);

        // 将Result对象转换为JSON字符串
        String jsonString = JSON.toJSONString(result);

        // 将JSON字符串写入响应
        writer.println(jsonString);

        // 刷新并关闭PrintWriter对象
        writer.flush();
        writer.close();

        // 返回false,表示请求应在此处停止
        return false;
    }
}

修改ShiroConfig

Springboot整合Shiro_第12张图片

 测试,不登录,直接访问:

Springboot整合Shiro_第13张图片

 4.shiro权限对象缓存到redis中

引入依赖

 
        
            org.crazycake
            shiro-redis
            3.3.1
        

修改 ShiroConfig

Springboot整合Shiro_第14张图片

 测试

Springboot整合Shiro_第15张图片

5.使用Swagger2接口文档测试

引入依赖

  
        
            io.github.jianzhichun
            spring-boot-starter-swagger2
            0.0.1
        
        
            com.github.xiaoymin
            swagger-bootstrap-ui
            1.9.6
        

创建swagger配置文件



import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;


@Configuration  //swagger配置文件
public class SwaggerConfig {


    @Bean     //加在方法上,表示把方法的返回结果交于spring容器来管理该对象,里面封装了接口文档的信息
    public Docket docket() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName("qy165第五组")
                .apiInfo(getInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.wqg.controller"))
                .build();

        return docket;
    }

    private ApiInfo getInfo() {
        Contact DEFAULT_CONTACT = new Contact("张三", "151******", "319***[email protected]");
        ApiInfo apiInfo = new ApiInfo("学生管理系统API文档", "学生管理系统API文档",
                "2.0", "http://localhost:8080/doc.html", DEFAULT_CONTACT,
                "游戏公司", "www.4399.com");
        return apiInfo;
    }
}

设置放行

Springboot整合Shiro_第16张图片

 测试http://localhost:8080/doc.html

Springboot整合Shiro_第17张图片

Springboot整合Shiro_第18张图片

你可能感兴趣的:(spring,boot,后端,java)