前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringSecurity 入门(一)

SpringSecurity 入门(一)

作者头像
是小张啊喂
发布2021-08-09 17:39:14
5600
发布2021-08-09 17:39:14
举报
文章被收录于专栏:软件

感觉现在的Java开发人员已经离不开Spring框架,不讨论这种事情是好是坏,但是确实好用,但是个人入门有些东西难度还是很高的,摸索的进度有些许的慢,只能慢慢的更新了,那今天就慢慢更新一期SpringSecurity的入门篇,完成完整的系统,可以直接投入生产开发使用。

如何开始

  1. 有一定的Java基础,会Spring BootSpring SecurityMyBatis plus
  2. 首先,明白什么是token
  3. token有什么样的作用
  4. 了解基础的角色权限验证

Token

先来体验一下什么是 token

代码语言:javascript
复制
package com.shaojie.authority.jwt;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.IdUtil;
import com.shaojie.authority.exception.TokenException;
import com.shaojie.authority.service.impl.AuthorityServiceImpl;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.sql.Date;

/**
 * @author: ShaoJie
 * @data: 2020年02月22日 18:17
 * @Description: jwt 生成校验 token
 */
@Slf4j
@Configuration
public class JwtUtil {

    /**
     * 认证关键key
     */
    String signingKey = "SigningKey";

    /**
     * 创建生成 token
     *
     * @return
     */
    public String createToken() {
        //30秒过期
        long now = System.currentTimeMillis();
        long exp = now + 1000 * 60;
        // builder 构建 token
        String token = Jwts.builder()
                // 设置唯一的 id
                .setId(IdUtil.simpleUUID())
                // 设置主题
                .setSubject("token")
                // 设置角色
                .claim("authorities", "admin")
                // 设置角色集
//                .addClaims()
                // 设置过期时间
                .setExpiration(new Date(exp))
                // 设置 token 签发的时间
                .setIssuedAt(new DateTime())
                // 设置签名 使用HS256算法,并设置SecretKey(字符串)  签名算法和秘钥
                .signWith(SignatureAlgorithm.HS256, signingKey)
                // 以下内容构建JWT并将其序列化为紧凑的,URL安全的字符串
                .compact();
        log.info("token:{}", token);
        return token;
    }

    /**
     * 解析 token
     *
     * @param token 用户的 token
     */
    public void parseToken(String token) throws TokenException {
        Claims claims = Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token).getBody();
        if (claims.equals(null))
            throw new TokenException();
        log.info("解析的数据:{}", claims);
    }

    public static void main(String[] args) {
        JwtUtil jwtUtil = new JwtUtil();
        String token = jwtUtil.createToken();
        try {
            jwtUtil.parseToken(token);
        } catch (TokenException e) {
            log.info("token 过期");
        }
        System.out.println(token);
    }

}
代码语言:javascript
复制
生成的token:
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJiZmNjYzRlOWQ5OWY0Mzc3YTI1MjBmNjkxZDM1NzkyMiIsInN1YiI6InRva2VuIiwiYWRtaW4iOiJTaGFvSmllIiwiZXhwIjoxNTk1NDA0MTU4LCJpYXQiOjE1OTU0MDQwOTh9.AjPDjf40BnAzgnU3mCpjMI8KYggEVR8264JATKg4cFc

解析到的token:
{jti=bfccc4e9d99f4377a2520f691d357922, sub=token, admin=ShaoJie, exp=1595404158, iat=1595404098}

解析创建的token不难发现其中包含的信息:当前的创建token的主题、角色、过期时间等

这只是学习运用的第一步,体验这种认证带来的方便,和便捷。然后进入到正题,开始更新这样的一期Spring Boot整合SpringSecurity

基础依赖

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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.2.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>top.lzmvlog</groupId>
    <artifactId>authority</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>authority</name>
    <description>Spring Boot 整合 JWT 做授权认证</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR4</spring-cloud.version>
    </properties>

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

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.22</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.6</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.3.2</version>
        </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.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.11.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

JwtUtil 创建校验工具

代码语言:javascript
复制
package top.lzmvlog.authority.util.jwt;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpStatus;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import top.lzmvlog.authority.exception.TokenException;
import top.lzmvlog.authority.util.date.DateUtil;

/**
 * @author ShaoJie
 * @Date 2020年05月12 15:16
 * @Description: 生成解析 token 的工具类
 */
@Component
@Slf4j
public class JwtUtil {

    /**
     * 签名密钥
     */
    @Value("${auth.token.signingKey}")
    private String signingKey;

    /**
     * 创建生成 token
     *
     * @return String 生成的 token
     */
    public String createToken(String account) {
        log.info("账号:{} 登录成功", account);
        return Jwts.builder()
                // 设置唯一的 ida
                .setId(IdUtil.simpleUUID())
                // 设置主要包含的信息
                .setSubject(account)
                // 设置过期时间
                .setExpiration(new DateUtil().getNowDateOneTime())
                // 设置 token 签发的时间
                .setIssuedAt(new DateTime())
                // 设置签名 使用HS256算法,并设置SecretKey(字符串)  签名算法和秘钥
                .signWith(SignatureAlgorithm.HS256, signingKey)
                // 以下内容构建JWT并将其序列化为紧凑的,URL安全的字符串
                .compact();
    }

    /**
     * 解析当前的 token
     *
     * @param token token 信息
     * @return String token种解析到的信息
     */
    public String parseToken(String token) {
        Claims claims = Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token).getBody();
        if (claims.equals(null))
            throw new TokenException(HttpStatus.HTTP_INTERNAL_ERROR, "token 信息错误 重新授权");
        return claims.getSubject();
    }

}

当前的JwtUtil并没有加入关于角色的任何信息,只是单纯的针对账号去授权,生成这样的一个token,当然你也可以将你的权限信息去进行授权,自行发散思维。

构建权限验证

代码语言:javascript
复制
package top.lzmvlog.authority.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import top.lzmvlog.authority.filter.JwtAuthenticationFilter;
import top.lzmvlog.authority.handler.JwtAccessDeniedHandler;

/**
 * @author ShaoJie
 * @Date 2020年05月12 14:36
 * @Description: 安全验证配置
 */
@Configuration
@EnableWebSecurity
public class SecurityVerificationConfiguration extends WebSecurityConfigurerAdapter {

    /**
     * 密码加密
     *
     * @return
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 拦截器
     */
    @Autowired
    public JwtAuthenticationFilter jwtAuthenticationFilter;

    /**
     * jwt 验证处理器
     */
    @Autowired
    public JwtAccessDeniedHandler jwtAccessDeniedHandler;

    /**
     * toekn 配置
     */
    @Autowired
    public TokenConfiguration tokenConfiguration;

    /**
     * 授权 、 验证
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                // 授权地址不需要验证
                .antMatchers("/auth/token").permitAll()
                // 用户注册地址
                .antMatchers("/user/registered").permitAll()
                // 其余的都需要校验
                .anyRequest().authenticated()
                .and()
                // 添加后置处理拦截器
                .addFilterAfter(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .exceptionHandling()
                // 访问拒绝处理程序
                .accessDeniedHandler(jwtAccessDeniedHandler)
                .and()
                .apply(tokenConfiguration)
                .and()
                // 取消 session 的状态
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .csrf().disable();
    }

}

BCryptPasswordEncoder官方提供的密码加密类,对注册的用户信息进行加密,例如用户的登录密码。

JwtAuthenticationFilter权限拦截器,用于拦截用户信息,进行权限校验。

JwtAccessDeniedHandler拒绝访问处理器。

TokenConfiguration适配器配置,用于修改默认的认证处理器,实现自定义的验证

下次更新将着重对这些类细谈其实现,尝鲜体验可访问我的 GitHub 查看 authority项目 clone

代码语言:javascript
复制
$ git clone https://github.com/lzmvlog/authority.git
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-07-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如何开始
  • Token
  • 基础依赖
  • JwtUtil 创建校验工具
  • 构建权限验证
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档