springboot+shiro整合前后端分离

springboot整合shiro重要的是shiro配置文件的编写
添加需要的jar包

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>
        <!--thymeleaf整合shiro的依赖-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.21</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </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>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

编写shiro配置类

package com.jws.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.jws.realm.MyRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
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 java.util.HashMap;
import java.util.Map;

/**
 * @author Jin
 * @date 2020/11/11 15:16
 * @packageName: com.jws.config
 * @cLassName: MyConfig
 * @description:
 * @version:
 */
@Configuration
public class ShiroConfiguration {

    /**
     * 创建密码匹配器
     * @return
     */
    @Bean(value = "credentialsMatcher")
    public HashedCredentialsMatcher credentialsMatcher(){
        HashedCredentialsMatcher credentialsMatcher=new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(2);
        return credentialsMatcher;
    }

    /**
     * 创建一个realmBean,自定义类
     * @param credentialsMatcher
     * @return
     */
    @Bean(value = "myRealm")
    public Realm realm(CredentialsMatcher credentialsMatcher){
        MyRealm myRealm=new MyRealm();
        myRealm.setCredentialsMatcher(credentialsMatcher);
        return myRealm;
    }

    /**
     * 创建securityManager核心对象bean
     * @param myRealm
     * @return securityManager
     */
    @Bean(value = "securityManager")
    public DefaultWebSecurityManager securityManager(Realm myRealm){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm);
        return securityManager;
    }

    /**
     * 这里bean的value值一定要与下面注册filterBean时添加shiro过滤器(TargetBeanName)的名字一致
     * @param securityManager
     * @return
     */
    @Bean(value = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //前后端分离时不需要设置
        shiroFilterFactoryBean.setLoginUrl("/index.html");
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //定义一个map设置请求的权限
        Map<String, String> map=new HashMap<>();
        map.put("/tologin","anon");
        map.put("/login","anon");
        map.put("/logout","logout");
        map.put("/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    @Bean
    public FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean(){
        FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean=new FilterRegistrationBean<>();
        DelegatingFilterProxy delegatingFilterProxy=new DelegatingFilterProxy();
        //与上面配置的shiro过滤器bean的名字一致
        delegatingFilterProxy.setTargetBeanName("shiroFilter");
        filterRegistrationBean.setFilter(delegatingFilterProxy);
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }

    /**
     * 这里是为了能在html页面引用shiro标签,
     */
    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
}

application.properties

server.port=8080
#配置数据源characterEncoding=utf8&useSSL=true&serverTimezone=UTC
spring.datasource.druid.url=jdbc:mysql://localhost:3306/test2?serverTimezone=Asia/Shanghai
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.username=root
spring.datasource.druid.password=0207

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

#清除thymeleaf缓存,实时显示页面
spring.thymeleaf.cache=false

controller代码

@Controller
public class MyController {

    /**
     * 可以给一个登陆页面方便测试
     * @return
     */
    @GetMapping("login")
    public String login(){
        return "login";
    }

    @GetMapping("main")
    public @ResponseBody CommonResult main(HttpSession session){
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        session.setAttribute("user",user);
        return new CommonResult(200,"登陆成功");
    }

    @GetMapping("logout")
    public @ResponseBody CommonResult logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return new CommonResult(200,"退出成功");
    }

    @GetMapping("tologin")
    public String toLogin(String username, String password){
        try {
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token=new UsernamePasswordToken(username,password);
            subject.login(token);
            return "redirect:main";
        }catch (Exception e){
            return "redirect:login";
        }
    }

    @GetMapping("query")
    @RequiresPermissions(value = "user:query")
    public @ResponseBody String query(){ return "user:query";}
    @GetMapping("insert")
    @RequiresPermissions(value = "user:insert")
    public @ResponseBody String insert(){ return "user:insert";}
    @GetMapping("delete")
    @RequiresPermissions(value = "user:delete")
    public @ResponseBody String delete(){ return "user:delete";}
    @GetMapping("update")
    @RequiresPermissions(value = "user:update")
    public @ResponseBody String update(){ return "user:update";}
    @GetMapping("export")
    @RequiresPermissions(value = "user:export")
    public @ResponseBody String export(){ return "user:export";}
}

验证未登录时继承shiro提供的未认证过滤器来处理未认证请求

public class LoginFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        response.setContentType("application/json; charset=UTF-8");
        CommonResult commonResult=new CommonResult(500,"未登录");
        response.getWriter().println(JSON.toJSONString(commonResult));
        return false;
    }
}

CommonResult实体类用来返回前端需要的json数据

public class CommonResult {
    //状态码
    private int status;
    //消息
    private String message;
    //是否成功
    private Boolean success;
    //存储数据
    private Map<String,Object> data=new HashMap<>();

    public CommonResult(int status, String message) {
        this.status = status;
        this.message = message;
    }

    //链式编程
    public static CommonResult ok(){
        CommonResult commonResult=new CommonResult();
        commonResult.status=200;
        commonResult.message="成功";
        commonResult.success=true;
        return commonResult;
    }

    //
    public static CommonResult error(){
        CommonResult commonResult=new CommonResult();
        commonResult.status=500;
        commonResult.message="失败";
        commonResult.success=false;
        return commonResult;
    }
    
    public CommonResult message(String msg){
        this.message=msg;
        return this;
    }

    public CommonResult status(Integer code){
        this.status =code;
        return this;
    }

    public CommonResult success(Boolean success){
        this.success=success;
        return this;
    }

    //存放数据
    public CommonResult put(String key,Object d){
        this.data.put(key,d);
        return this;
    }
}

定义一个异常类来处理未授权异常

@RestControllerAdvice
public class HandlerGlobaleException {
    @ExceptionHandler(value = UnauthorizedException.class)
    public CommonResult handler(){
        return new CommonResult(500,"未授权");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

J_wensHeng

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

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

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

打赏作者

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

抵扣说明:

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

余额充值