SpringBoot整合Shiro和Swagger

Shiro是一款十分好用的权限管理框架 可以和SpringBoot整合实现页面的权限控制

首先导入pom依赖

<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

然后自定义我们的Realm对象 (配置类中需要这个类) 并且需要在Realm类中实现我们的授权认证(Shiro的核心)

package com.jee.shiro;

import com.jee.entity.User;
import com.jee.mapper.UserMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;


//自定义的 UserRealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserMapper userMapper;
    //授权(在访问需要权限的页面是  才会进行授权)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权 AuthorizationInfo");

        //授权 登录成功的
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获得当前对象
        Subject subject = SecurityUtils.getSubject();
        //获得认证中添加的当前用户的信息
        User currentUser = (User)subject.getPrincipal();
        //一般是通过这个User 查询数据库中对应的权限 然后给他授权
        //这里模拟一下就行
        System.out.println("id:"+currentUser.getId());
        info.addStringPermission("id:"+currentUser.getId());
        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了认证 AuthenticationInfo");
        //用户名 密码  从数据库中取
//        String name = "root";
//        String passwod = "123456";
        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        User user = userMapper.getUserByName(userToken.getUsername());
        //如果用户名不存在
        if(user == null){
            return null; //抛出异常  用户名不存在的异常
        }
        //如果用户名通过  就要验证密码了  验证密码是 shiro自己做的
        //第一个参数principal 表示存放在当前登录用户中的信息 添加后可以使用subject.getPrincipal方法获得
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }
}

最后再编写我们的Shiro配置类 实现自定义Shiro
很多的死代码 有一部分是需要我们自己配置的 详细看注释

package com.jee.config;

import com.jee.shiro.UserRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

@Configuration
public class ShiroConfig {

    //ShiroFilterFactoryBean (第三步)
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        //大部分死代码
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        //添加shiro的内置过滤器
        /*
            anon : 无需验证就可以访问
            authc: 必须要认证才可以访问
            user: 必须拥有记住我功能才可以访问
            perms: 拥有对某个资源的权限才可以访问
            role: 拥有某个角色权限才可以访问
         */
        Map<String,String> filterMap = new LinkedHashMap<>();
        //只需要自己填写一些需要验证的请求即可
        //将'/delete'的请求设置需要验证才可以访问
        filterMap.put("/delete","authc");
        //将'/query'的请求设置为: 必须通过授权才可以 并且添加授权的字段为id:3
        filterMap.put("/query","perms[id:3]");
        bean.setFilterChainDefinitionMap(filterMap);
        //需要手动设置   设置登录的页面 (在Control层写一个toLogin的请求 跳转到真正的登录页面
        bean.setLoginUrl("/toLogin");
        return bean;
    }

    //DefaultWebSecurityManager (第二步)
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
        //死代码
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联UserRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //创建 realm 对象 (第一步) 需要自定义类
    @Bean
    public UserRealm userRealm(){
        //死代码  只需要return 自定义的Realm类即可
        return new UserRealm();
    }
}

相应的Controller:

package com.jee.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jee.entity.User;
import com.jee.mapper.UserMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
public class MyController {

    @Autowired
    private UserMapper userMapper;

    @RequestMapping("/aa")
    @ResponseBody
    public String fun1() throws JsonProcessingException {
        List<User> allUser = userMapper.getAllUser();
        ObjectMapper mapper = new ObjectMapper();
        return (mapper.writeValueAsString(allUser));
    }

    @RequestMapping("/bb")
    @ResponseBody
    public String fun2(){
        return "Hello Spring";
    }

    @GetMapping("/query")
    public String fun3(){
        return "user/query";
    }

    @GetMapping("/delete")
    public String fun4(){
        return "user/delete";
    }

    @RequestMapping("/toLogin")
    public String fun5(){
        return "user/login";
    }

    @PostMapping("/login")
    public String fun6(String userName,String passWord){
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord);
        //设置记住我
        token.setRememberMe(true);
        try {
            subject.login(token);//执行登录的方法 如果没有异常就说明Ok了
            return "hh";
        }catch (UnknownAccountException e){//用户名不存在
            System.out.println("用户名错误");
            return "user/login";
        }catch (IncorrectCredentialsException e){//密码不存在
            System.out.println("密码错误");
            return "user/login";
        }
    }
}

SpringBoot集成Swagger2

导入依赖

 <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

编写相应的配置类:

package com.jee.config;

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;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;

@Configuration
//开启Swagger2功能
@EnableSwagger2
public class SwaggerConfig {

    //配置Swagger的Docket的bean实例
    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
                .select()//选择扫描的方式
                //RequestHandlerSelectors  配置扫描的方式
                //basePackage: 指定要扫描的包(常用)
                //any : 扫描全部
                //none: 全都不扫描
                //withClassAnnotation : 扫描类上面的注解,参数是一个注解的反射对象
                //withMethodAnnotation : 扫描方法上的注解
                .apis(RequestHandlerSelectors.basePackage("com.jee.controller"))
                .build();
    }

    //配置Swagger的信息 apiInfo
    private ApiInfo apiInfo(){
        //作者信息
        Contact contact = new Contact("Jee","(url)xxx","[email protected]");
        return new ApiInfo(
                "Jee的SwaggerAPI文档",
                "(文档的描述)",
                "(版本号)",
                "(url)",
                contact,
                "(license)",
                "licenseUrl",
                new ArrayList()
        );

    }
}

然后可以去swagger-ui界面查看相关信息
在这里插入图片描述

发布了53 篇原创文章 · 获赞 0 · 访问量 1943

猜你喜欢

转载自blog.csdn.net/XXuan_/article/details/104876050