SpringBoot+Shiro+Jwt实现登录认证——最干的干货

本文详细介绍了如何使用SpringBoot结合Shiro和Jwt实现登录认证。首先概述了SpringBoot、Shiro和Jwt的基本概念,接着讲解了SpringBoot整合Shiro的两种方法,包括使用starter和不使用starter的配置。然后阐述了SpringBoot整合Jwt的步骤,包括依赖和代码实现。最后,详细描述了SpringBoot+Shiro+Jwt的认证流程及快速开始的步骤,涉及JwtFilter、JwtToken、JwtRealm的创建等。
摘要由CSDN通过智能技术生成

1. 概述

1.1 SpringBoot

这个就没什么好说的了,能看到这个教程的,估计都是可以说精通了SpringBoot的使用

1.2 Shiro

一个安全框架,但不只是一个安全框架。它能实现多种多样的功能。并不只是局限在web层。在国内的市场份额占比高于SpringSecurity,是使用最多的安全框架

可以实现用户的认证和授权。比SpringSecurity要简单的多。

1.3 Jwt

我的理解就是可以进行客户端与服务端之间验证的一种技术,取代了之前使用Session来验证的不安全性

为什么不适用Session?

原理是,登录之后客户端和服务端各自保存一个相应的SessionId,每次客户端发起请求的时候就得携带这个SessionId来进行比对

  1. Session在用户请求量大的时候服务器开销太大了
  2. Session不利于搭建服务器的集群(也就是必须访问原本的那个服务器才能获取对应的SessionId)

它使用的是一种令牌技术

Jwt字符串分为三部分

  1. Header

    存储两个变量

    1. 秘钥(可以用来比对)
    2. 算法(也就是下面将Header和payload加密成Signature)
  2. payload

    存储很多东西,基础信息有如下几个

    1. 签发人,也就是这个“令牌”归属于哪个用户。一般是userId
    2. 创建时间,也就是这个令牌是什么时候创建的
    3. 失效时间,也就是这个令牌什么时候失效
    4. 唯一标识,一般可以使用算法生成一个唯一标识
  3. Signature

    这个是上面两个经过Header中的算法加密生成的,用于比对信息,防止篡改Header和payload

然后将这三个部分的信息经过加密生成一个JwtToken的字符串,发送给客户端,客户端保存在本地。当客户端发起请求的时候携带这个到服务端(可以是在cookie,可以是在header,可以是在localStorage中),在服务端进行验证

好了,废话不多说了,下面开始实战,实战分为以下几个部分

  1. SpringBoot整合Shiro
  2. SpringBoot整合Jwt
  3. SpringBoot+Shiro+Jwt
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.11.0</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

2. SpringBoot整合Shiro

两种方式:

  1. 将ssm的整合的配置使用java代码方式在springBoot中写一遍
  2. 使用官方提供的start

2.1 使用start整合springBoot

pom.xml

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-web-starter</artifactId>
    <version>1.4.0</version>
</dependency>
<!--注意不要写成shiro-spring-boot-starter-->

application.properties

shiro.loginUrl="xxx"
#认证不通过的页面
shiro.UnauthorizedUrl="xxx"
#授权不通过的跳转页面

创建ShiroConfig.java进行一些简单的配置

@Configuration
public class SpringShiroConfig {
    @Bean
    public Realm customRealm() {
        return new CustomRealm();
    }
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(customRealm());
        // 关闭 ShiroDAO 功能
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        // 不需要将 Shiro Session 中的东西存到任何地方(包括 Http Session 中)
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        return securityManager;
    }
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chain = new DefaultShiroFilterChainDefinition();
        // 哪些请求可以匿名访问
        chain.addPathDefinition("/login", "anon");      // 登录接口
        chain.addPathDefinition("/notLogin", "anon");   // 未登录错误提示接口
        chain.addPathDefinition("/403", "anon");    // 权限不足错误提示接口
        // 除了以上的请求外,其它请求都需要登录
        chain.addPathDefinition("/**", "authc");
        return chain;
    }
    // Shiro 和 Spring AOP 整合时的特殊设置
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
}

//还有关闭ShiroDao功能

创建自定义的Realm

public class CustomRealm extends AuthorizingRealm {
    private static final Set<String> tomRoleNameSet = new HashSet<>();
    private static final Set<String> tomPermissionNameSet = new HashSet<>();
    private static final Set<String> jerryRoleNameSet = new HashSet<>();
    private static final Set<String> jerryPermissionNameSet = new HashSet<>();
    static {
        tomRoleNameSet.add("admin");
        jerryRoleNameSet.add("user");
        tomPermissionNameSet.add("user:insert");
        tomPermissionNameSet.add("user:update");
        tomPermissionNameSet.add("user:delete");
        tomPermissionNameSet.add("user:query");
        jerryPermissionNameSet.add("user:query");
    }
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo info =  new SimpleAuthorizationInfo();
        if (username.equals("tom")) {
            info.addRoles(tomRoleNameSet);
            info.addStringPermissions(tomPermissionNameSet);
        } else if (username.equals("jerry")) {
            info.addRoles(jerryRoleNameSet);
            info.addStringPermissions(jerryPermissionNameSet);
        }
        return info;
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        if (username == null)
           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值