springboot整合shiro

本文详细介绍了如何在SpringBoot项目中整合Shiro框架,包括添加相关依赖、配置application文件、创建Shiro配置类、设置controller、dao、entity、filter、handler、realm等各层的实现,以及service和util层的细节,旨在提供一个完整的Shiro整合教程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1 依赖

2 application配置文件

3 创建shiro配置类

4 controller层

5 dao层

6 entity层

7 filter层

8 handler层

9 realm层

11 uilt层


1 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xzj</groupId>
    <artifactId>springboot-shiro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-shiro</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
            <version>1.9.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.7.8</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.7.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2 application配置文件

#数据源
spring.datasource.url=jdbc:mysql://localhost:3306/shiro?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#端口号
server.port=8808

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

3 创建shiro配置类

package com.xzj.config;

import com.xzj.filter.LoginFilter;
import com.xzj.realm.MyRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
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.HashSet;

/**
 * @author xuan
 */
@Configuration
public class shiroConfig {
    @Bean
    public DefaultWebSecurityManager securityManager(){
       DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
       securityManager.setRealm(realm());
       return securityManager;
    }

    @Bean
    public Realm realm(){
        MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(credentialsMatcher());
        return  myRealm;
    }
    @Bean
    public CredentialsMatcher credentialsMatcher (){
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(1024);
        return credentialsMatcher;
    }

    @Bean(value = "shiroFilter")
    public ShiroFilterFactoryBean filterFactoryBean(){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager());
        HashMap<String, String> map = new HashMap<>();
        map.put("/login","anon");
        map.put("/*.css","anon");
        map.put("/doc.html","anon");
        map.put("/v2/api-docs", "anon");
        map.put("/configuration/security","anon");
        map.put("/swagger-resources", "anon");
        map.put("/configuration/ui", "anon");
        map.put("/**","authc");
        factoryBean.setFilterChainDefinitionMap(map);

        HashMap<String, Filter> filterMap = new HashMap<>();
        filterMap.put("authc",new LoginFilter());
        factoryBean.setFilters(filterMap);
        return factoryBean;
    }
    @Bean
    public FilterRegistrationBean<Filter> filterRegistrationBean(){
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setName("shiroFilter");
        filterRegistrationBean.setFilter(new DelegatingFilterProxy());
        return filterRegistrationBean;
    }
    //开始shiro注解
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
}

swagger

package com.xzj.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.service.VendorExtension;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.ArrayList;

/**
 * @author xuan
 */
@Configuration
public class SwaggerConfig {
    @Bean
    public Docket docket(){
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xzj.controller"))
                .build();
          return docket;

    }

    public ApiInfo apiInfo(){
        Contact DEFAULT_CONTAT=new Contact("xzj","http://www.aaa.com","111@qq.com");
        ApiInfo apiInfo= new ApiInfo("qy151在线文档","这是一个文档","A1.0","http://www.aaa.com",
                DEFAULT_CONTAT,"AAA","http://www.aaa.com",new ArrayList<VendorExtension>());
        return  apiInfo;
    }
}

4 controller层

登录

package com.xzj.controller;

import com.xzj.util.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author xuan
 */
@RestController
@Api(value = "登陆页面")
public class LoginController {
    @PostMapping("/login")
    @ApiOperation(value = "登录")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "账号",name="username",required = true),
            @ApiImplicitParam(value = "密码",name="userpwd",required = true)
    })
    public CommonResult login (String username,String userpwd){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username,userpwd);
        try{
            subject.login(token);
            return new CommonResult(2000,"登录成功",null);
        }catch (Exception e){
            e.printStackTrace();
            return new CommonResult(5000,"登录失败",null);
        }
    }
}

用户

package com.xzj.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author xuan
 */
@RestController
@RequestMapping("/user")
@Api(value = "User接口")
public class UserCotroller {
    @GetMapping("/query")
    @ApiOperation(value = "查看操作")
    @RequiresPermissions(value={"/user/query"})
    public String query(){
        return "user:query";
    }

    @GetMapping("/update")
    @ApiOperation(value = "修改操作")
    @RequiresPermissions(value={"/user/update"},logical = Logical.OR)
    public String update(){
        return "user:update";
    }

    @GetMapping("/insert")
    @ApiOperation(value = "添加操作")
    @RequiresPermissions(value={"/user/insert"})
    public String add(){
        return "user:insert";
    }

    @GetMapping("/delete")
    @ApiOperation(value = "删除操作")
    @RequiresPermissions(value={"/user/delete"})
    public String delete(){
        return "user:delete";
    }

    @GetMapping("/export")
    @ApiOperation(value = "导出操作")
    @RequiresPermissions(value={"/user/export"})
    public String export(){
        return "user:export";
    }
}

5 dao层

package com.xzj.dao;


import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.xzj.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;


import java.util.List;

@Mapper
public interface UserDao extends BaseMapper<User> {
    @Select(value = "select percode from user_role ur join role_permission rp on ur.roleid=rp.roleid join permission p on  rp.perid=p.perid where ur.userid=#{userid}")
    List<String> selectByUserId(Integer userid);

}

6 entity层

package com.xzj.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author xuan
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private  Integer userid;
    private  String username;
    private  String userpwd;
    private  String sex;
    private  String address;
    private  String salt;
}

7 filter层

package com.xzj.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzj.util.CommonResult;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.PrintWriter;

/**
 * @author xuan
 */
public class LoginFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        CommonResult commonResult = new CommonResult(4001,"未登录",null);
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(commonResult);
        writer.print(json);
        writer.flush();
        writer.close();
        return false;
    }
}

8 handler层

package com.xzj.handler;

import com.xzj.util.CommonResult;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author xuan
 */
@ControllerAdvice
public class MyException {
    @ExceptionHandler(value = UnauthorizedException.class)
    @ResponseBody
    public CommonResult aunth(UnauthorizedException e){
        e.printStackTrace();
        return  new CommonResult(4002,"权限不足",null);
    }
}

9 realm层

package com.xzj.realm;

import com.xzj.entity.User;
import com.xzj.service.UserService;
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.List;

/**
 * @author xuan
 */
public class MyRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        User user = (User) principalCollection.getPrimaryPrincipal();

        List<String> list = userService.selectByUserId(user.getUserid());
        if(list!=null&&list.size()>0){
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.addStringPermissions(list);
            return info;
        }

        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String) authenticationToken.getPrincipal();
        User user= userService.findByUsername(username);
        if(user!=null){
            ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,
                    user.getUserpwd(),credentialsSalt,this.getName());
            return info;
        }
        return null;
    }
}

10 service层

package com.xzj.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xzj.dao.UserDao;
import com.xzj.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author xuan
 */
@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    public User findByUsername(String username) {
       QueryWrapper<User> wrapper = new QueryWrapper<>();
       wrapper.eq("username",username);
        User user = userDao.selectOne(wrapper);
        return user;
    }

    public List<String> selectByUserId(Integer userid) {
        List<String> list =userDao.selectByUserId(userid);

        return list;
    }


}

11 uilt层

package com.xzj.util;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author xuan
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "统一json数据")
public class CommonResult {
    @ApiModelProperty("状态码2000表示成功 5000表示失败")
    private Integer code;
    @ApiModelProperty("响应的消息内容")
    private String msg;
    @ApiModelProperty("相应的数据")
    private Object data;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值