Springboot Security and JWT 快速入门实战(下)

简介: Springboot Security and JWT 快速入门实战
目录结构

image.png

此时完成了添加端点signin到自定义拦截链中

测试应用


此时接口api/hello,仍然是没有权限的,我们添加jwt的支持。

添加JWT

依赖添加
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
开发token生成类
package com.example.demo.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Base64;
import java.util.Date;
/**
 * @author 小隐乐乐
 * @since 2020/11/8 20:38
 */
@Component
public class JwtProvider {
    private String secretKey;
    private long validityInMilliseconds;
    @Autowired
    public JwtProvider(@Value("${security.jwt.token.secret-key}") String secretKey,
                       @Value("${security.jwt.token.expiration}") long milliseconds) {
        this.secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
        this.validityInMilliseconds = milliseconds;
    }
    public String createToken(String username) {
        //Add the username to the payload
        Claims claims = Jwts.claims().setSubject(username);
        //Build the Token
        Date now = new Date();
        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(now)
                .setExpiration(new Date(now.getTime() + validityInMilliseconds))
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
    }
}

create Token方法使用jjwt库创建JWT令牌。用户名就是有效负载的主题。它是使用属性文件中的密钥签名的,并且令牌的有效性也在属性文件中指定。结果令牌将具有Header.Payload.Signature的格式。标头包含类型(JSON Web令牌)和哈希算法(HMAC SHA256)。有效负载又称包含令牌的主题(子),数字日期值(exp)中的到期日期,发布JWT的时间(iat),唯一的JWT标识符(jti)以及由冒号分隔的特定于应用程序的键值对。签名是使用嵌入在应用程序中的密钥的标头和有效负载的哈希值。

配置文件修改
security.jwt.token.secret-key=jwt-token-secret-key-for-encryption
security.jwt.token.expiration=1200000
开发web filter
package com.example.demo.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Base64;
import java.util.Date;
import java.util.Optional;
import java.util.function.Function;
/**
 * @author 小隐乐乐
 * @since 2020/11/8 20:46
 */
public class JwtTokenFilter extends GenericFilterBean {
    private String secret;
    private static final String BEARER = "Bearer";
    private UserDetailsService userDetailsService;
    public JwtTokenFilter(UserDetailsService userDetailsService, String secret) {
        this.userDetailsService = userDetailsService;
        this.secret = Base64.getEncoder().encodeToString(secret.getBytes());
    }
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
            throws IOException, ServletException {
        String headerValue = ((HttpServletRequest) req).getHeader("Authorization");
        getBearerToken(headerValue).ifPresent(token -> {
            String username = getClaimFromTokenS((String) token, Claims::getSubject);
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if (username.equals(userDetails.getUsername()) && !isJwtExpired((String) token)) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails((HttpServletRequest) req));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        });
        filterChain.doFilter(req, res);
    }
    private Optional getBearerToken(String headerVal) {
        if (headerVal != null && headerVal.startsWith(BEARER)) {
            return Optional.of(headerVal.replace(BEARER, "").trim());
        }
        return Optional.empty();
    }
    private Date getClaimFromToken(String token, Function<Claims, Date> claimsResolver) {
        final Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
        return claimsResolver.apply(claims);
    }
    private String getClaimFromTokenS(String token, Function<Claims, String> claimsResolver) {
        final Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
        return claimsResolver.apply(claims);
    }
    private boolean isJwtExpired(String token) {
        Date expirationDate = getClaimFromToken(token, Claims::getExpiration);
        return expirationDate.before(new Date());
    }
}

这与Java EE中的Web过滤器相同。此Web筛选器检查令牌是否已过期(即Jwt已过期)。它解析有效负载,获取来自令牌的Claims。它将剥离承载字符串,该字符串是授权标头的值。如果令牌通过了所有检查,则do Filter方法将配置Spring安全性以在上下文中手动设置身份验证。我们指定当前用户已通过身份验证,以使其成功通过。

接下来是在Web安全配置类中添加一些行。

WebSecurityConfiguration改造
package com.example.demo.config;
import com.example.demo.jwt.JwtTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
 * @author 小隐乐乐
 * @since 2020/11/8 20:20
 */
@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Value("${security.jwt.token.secret-key}")
    private String secret;
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/signin").permitAll()
                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(new JwtTokenFilter(userDetailsService, secret), UsernamePasswordAuthenticationFilter.class);
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }
}
接口类改造
package com.example.demo.controller;
import com.example.demo.dto.SigninDto;
import com.example.demo.jwt.JwtProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
 * @author 小隐乐乐
 * @since 2020/11/8 19:44
 */
@RestController
@RequestMapping("/api")
public class HelloController {
    @Autowired
    private JwtProvider jwtProvider;
    @Autowired
    private AuthenticationManager authenticationManager;
    @GetMapping("/hello")
    public String hello() {
        return "hello guys";
    }
    @PostMapping("/signin")
    public String signIn(@RequestBody @Valid SigninDto signInDto) {
        try {
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(signInDto.getUsername(), signInDto.getPassword()));
            return jwtProvider.createToken(signInDto.getUsername());
        } catch (AuthenticationException e) {
            System.out.println("Log in failed for user, " + signInDto.getUsername());
        }
        return "";
    }
}
测试应用
signin接口调用获取token


hello接口调用携带token


总结

Spring Boot Security和JWT Hello World示例已完成。总而言之,当登录身份验证通过时,我们将创建一个JSON Web令牌并将其返回给调用方。然后,调用方将JWT放置在标头中,并在其后续的GET请求中使用授权密钥。 Web过滤器检查令牌的有效性。如果有效,Web过滤器将使其通过过滤器链并返回“ Hello world”。


目录
相关文章
|
11天前
|
JSON 安全 Java
什么是JWT?如何使用Spring Boot Security实现它?
什么是JWT?如何使用Spring Boot Security实现它?
48 5
|
2月前
|
JSON 安全 算法
|
17天前
|
JSON 安全 算法
Spring Boot 应用如何实现 JWT 认证?
Spring Boot 应用如何实现 JWT 认证?
45 8
|
1月前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
38 0
|
JSON 算法 安全
SpringBoot从入门到精通(三十四)如何集成JWT实现Token验证
近年来,随着前后端分离、微服务等架构的兴起,传统的cookie+session身份验证模式已经逐渐被基于Token的身份验证模式取代。接下来介绍如何在Spring Boot项目中集成JWT实现Token验证。
SpringBoot从入门到精通(三十四)如何集成JWT实现Token验证
|
JSON 算法 Java
SpringBoot集成JWT实现token验证
JWT官网: https://jwt.io/JWT(Java版)的github地址:https://github.com/jwtk/jjwt 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息。
3837 0
|
Java
Java:SpringBoot集成JWT实现token验证
Java:SpringBoot集成JWT实现token验证
217 0
Java:SpringBoot集成JWT实现token验证
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
166 1
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
108 62
|
6天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。

热门文章

最新文章