mall整合SpringSecurity及JWT实现认证授权实战

来分享一下“mall整合SpringSecurity及JWT实现认证授权实战”的完整攻略。

1. 环境准备

要完成该攻略,首先需要准备好以下环境:

  • JDK 1.8+
  • Maven 3.x
  • IntelliJ IDEA 2019.2+(或其他任意IDE)

2. 创建maven项目

使用maven创建一个空白的Spring Boot项目,并引入必要的依赖,包括Spring Boot、Spring Security和JWT等。

3. 配置Spring Security

创建一个继承WebSecurityConfigurerAdapter的配置类,重写configure()方法以进行身份验证和授权设置。其中包括:

  • 配置用户身份验证方式:可以通过数据库、自定义验证等方式进行用户验证。
  • 配置权限验证:可以通过@PreAuthorize@PostAuthorize注解进行方法级别的授权。

示例:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/public/**").permitAll() // 允许公开访问的url
                .anyRequest().authenticated() // 其余的URL需要身份验证
                .and()
            .formLogin()
                .loginPage("/login") // 登录页面URL
                .loginProcessingUrl("/doLogin") // 登录接口URL
                .usernameParameter("username") // 登录用户名参数
                .passwordParameter("password") // 登录密码参数
                .successHandler(new MyAuthenticationSuccessHandler()) // 登录成功的处理器
                .failureHandler(new MyAuthenticationFailureHandler()) // 登录失败的处理器
                .permitAll()
                .and()
            .logout()
                .logoutUrl("/logout") // 退出登录的接口URL
                .logoutSuccessUrl("/login") // 退出成功后跳转的URL
                .permitAll();

        http.csrf().disable(); // 禁用CSRF保护
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());
    }
}

注:上述示例中,我们使用了BCryptPasswordEncoder加密方式对用户密码进行加密。

4. 配置JWT

pom.xml文件中添加以下依赖:

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

接着,我们需要创建一个JWT工具类,实现JWT的生成和解析等功能。

示例:

@Component
public class JwtUtils {

    /**
     * 过期时间,单位:分钟
     */
    private static final long EXPIRATION = 30;

    /**
     * 秘钥
     */
    private static final String SECRET_KEY = "mall";

    /**
     * 创建JWT Token
     *
     * @param subject 用户信息
     * @return JWT Token
     */
    public String createToken(String subject) {
        Date now = new Date();
        Date expirationDate = new Date(now.getTime() + EXPIRATION * 60 * 1000);
        return Jwts.builder()
                .setSubject(subject)
                .setIssuedAt(now)
                .setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
                .compact();
    }

    /**
     * 解析JWT Token,并返回其中的subject(用户信息)
     *
     * @param token JWT Token
     * @return 用户信息
     */
    public String parseToken(String token) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(SECRET_KEY)
                    .parseClaimsJws(token)
                    .getBody();
            return claims.getSubject();
        } catch (Exception e) {
            return null;
        }
    }
}

5. 添加JWT认证

为了使用JWT进行身份验证,我们需要修改WebSecurityConfig类以支持JWT。

示例:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtUtils jwtUtils;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/public/**").permitAll() // 允许公开访问的url
                .anyRequest().authenticated() // 其余的URL需要身份验证
                .and()
            .formLogin()
                .loginPage("/login") // 登录页面URL
                .loginProcessingUrl("/doLogin") // 登录接口URL
                .usernameParameter("username") // 登录用户名参数
                .passwordParameter("password") // 登录密码参数
                .successHandler(new MyAuthenticationSuccessHandler()) // 登录成功的处理器
                .failureHandler(new MyAuthenticationFailureHandler()) // 登录失败的处理器
                .permitAll()
                .and()
            .logout()
                .logoutUrl("/logout") // 退出登录的接口URL
                .logoutSuccessUrl("/login") // 退出成功后跳转的URL
                .permitAll();

        http.csrf().disable(); // 禁用CSRF保护

        // 添加JWT认证
        http.addFilterBefore(new JwtAuthenticationFilter(jwtUtils), UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());
    }
}

然后,我们需要创建一个JwtAuthenticationFilter,用于验证JWT,并将用户信息添加到spring security的上下文中。

示例:

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private JwtUtils jwtUtils;

    public JwtAuthenticationFilter(JwtUtils jwtUtils) {
        this.jwtUtils = jwtUtils;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authorization = request.getHeader("Authorization");
        if (authorization != null && authorization.startsWith("Bearer ")) {
            String jwt = authorization.substring(7);
            String subject = jwtUtils.parseToken(jwt);
            if (subject != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = userDetailsService.loadUserByUsername(subject);
                if (jwtUtils.validateToken(jwt, userDetails)) {
                    UsernamePasswordAuthenticationToken authenticationToken =
                            new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                }
            }
        }
        filterChain.doFilter(request, response);
    }
}

6. 测试

现在我们可以进行测试了。我们可以编写一个测试接口,例如/api/test,来测试JWT认证是否生效。

示例:

@RestController
@RequestMapping("/api")
public class TestController {

    @GetMapping("/test")
    @PreAuthorize("hasRole('ADMIN')")
    public String test() {
        return "Hello, World!";
    }
}

其中,@PreAuthorize("hasRole('ADMIN')")表示只有具有ADMIN角色的用户才能访问该接口。

接下来,我们可以在Postman或其他工具中发送请求进行测试。请求头中需要携带如下信息:

Authorization:Bearer {JWT Token}

其中,JWT Token可以通过JwtUtils工具类生成。

如果授权成功,接口将返回“Hello, World!”消息。

这就是使用Spring Security和JWT实现认证授权的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:mall整合SpringSecurity及JWT实现认证授权实战 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • 什么是标记-清除算法?

    以下是关于标记-清除算法的详细讲解: 什么是标记-清除算法? 标记-清除算法是一种常见的垃圾回收算法,它的原理是在程序运行过程中,标记所有不再使用的内存空间,然后清除这些内存空间,从而回收内存空间。标记清除算法分为两个阶段:标记阶段和清除阶段。 标记阶段 在标记阶段,垃圾回收器会遍历所有的对象,标记所有不再使用的对象。标记的方式通常是在对象头中添加一个标记位…

    Java 2023年5月12日
    00
  • JavaSpringBoot报错“TransactionSystemException”的原因和处理方法

    当使用Java的Spring Boot框架时,可能会遇到“TransactionSystemException”错误。这个错误通常是由以下原因之一引起的: 事务管理器配置错误:如果事务管理器配置错误,则可能会出现此错误。在这种情况下,需要检查事务管理器的配置并进行必要的更改。 事务注解使用错误:如果事务注解使用错误,则可能会出现此错误。在这种情况下,需要检查…

    Java 2023年5月5日
    00
  • 关于Java利用反射实现动态运行一行或多行代码

    Java反射是指通过运行时借助Java API获取对象信息的机制。反射允许我们在程序运行时动态获取类的相关信息、构造实例、调用方法、访问和修改字段属性等。在一些特殊的需求场景下,我们可以利用Java的反射机制来实现动态运行一行或多行代码。以下是具体实现步骤: 1. 获取指定类的Class对象 在Java中,所有的类都是对象,每个类都有一个Class对象。获取…

    Java 2023年5月26日
    00
  • Javaweb使用Maven工具与Tomcat的方法详解

    Javaweb使用Maven工具与Tomcat的方法详解 什么是Maven? Maven是一个Java项目管理工具,它可以帮助我们管理项目的依赖,构建,测试等工作。 为什么需要Maven? 抽象依赖关系,易于维护 统一构建方式,减少人为出错 有助于代码重用 前置条件 在开始Maven项目之前,您需要做一些准备工作: 安装Java JDK 安装Apache M…

    Java 2023年5月20日
    00
  • Spring Data Jpa框架最佳实践示例

    下面是针对“Spring Data JPA框架最佳实践示例”的详细攻略。 1. 简介 Spring Data JPA 旨在为JPA 提供更加方便的数据访问和处理方式。通过Spring Data JPA,我们可以减少很多代码量,这部分代码通常是模板式重复的。这样我们的代码可以更加专注于业务逻辑的实现。通过以下示例,了解如何使用Spring Data JPA 完…

    Java 2023年6月2日
    00
  • 在jsp页面中响应速度提高的7种方法分享

    “在jsp页面中响应速度提高的7种方法分享”是一篇介绍如何提升jsp页面响应速度的文章。下面我们来逐一讲解这7条方法。 1. 压缩页面 在jsp页面中,压缩页面可以减少文件大小,从而减少传输时间,提高页面加载速度。可以使用GZIP、BZIP等压缩技术进行压缩。在jsp中,可以使用filter过滤器来实现页面压缩。以下是一个示例: public class C…

    Java 2023年6月15日
    00
  • 微信小程序实现日期格式化

    下面我将详细讲解微信小程序实现日期格式化的完整攻略。 一、需求分析 在实际开发中,我们通常需要将日期格式化为特定的字符串格式,以便于展示给用户。比如,将 “2022/02/22 22:22:22” 格式化为 “2022年2月22日 22时22分22秒”。 微信小程序提供了 Date 对象来处理日期,但是该对象没有提供日期格式化的方法。因此,我们需要自己来实现…

    Java 2023年5月23日
    00
  • Spring Boot构建框架详解

    SpringBoot构建框架详解 什么是SpringBoot SpringBoot是由Pivotal团队在2013年开源的一款基于Java的框架,它旨在让开发者更加便捷地创建Spring应用。SpringBoot具备自动配置、快速开发、无代码生成等特点,同时它也提供了包括Web、数据、消息等在内的一系列开发场景。 如何使用SpringBoot 1. 环境要求…

    Java 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部