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

想要实现基于SpringSecurity和JWT的认证和授权,一般需要遵循以下步骤:

  1. 添加相关依赖

添加Spring Security和JWT相关依赖:

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

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>
  1. 实现UserDetails接口和自定义UserDetailsService
public class UserDetailsImpl implements UserDetails {
    private Long id;
    private String username;
    private String password;
    private Collection<? extends GrantedAuthority> authorities;
    // getter and setter
}

public class UserDetailsServiceImpl implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 根据用户名查找用户,并将其转换为UserDetailsImpl
    }
}
  1. 配置Spring Security
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/api/v1/login").permitAll()
            .anyRequest().authenticated()
            .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and().addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

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

    @Bean
    public JwtUtils jwtUtils() {
        // JwtUtils是自己实现的生成和解析JWT的工具类
        return new JwtUtils();
    }
}
  1. 编写JwtAuthenticationFilter
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Autowired
    private JwtUtils jwtUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        String token = jwtUtils.getToken(httpServletRequest);
        if (StringUtils.isNotBlank(token) && jwtUtils.validateToken(token)) {
            String username = jwtUtils.getUsernameFromToken(token);
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                if (jwtUtils.validateToken(token, userDetails)) {
                    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                }
            }
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }
}
  1. 为登录和注册接口添加认证和授权功能

在登录和注册接口中添加相应的认证和授权功能,并在登录成功时返回JWT:

@RestController
@RequestMapping("/api/v1")
public class UserController {
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtUtils jwtUtils;

    @PostMapping("/login")
    public String login(@RequestBody LoginRequest loginRequest) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        return jwtUtils.generateToken(userDetails);
    }

    @PostMapping("/register")
    public User register(@RequestBody RegistrationRequest registrationRequest) {
        // 处理注册请求
    }
}

以下是两个示例:

示例1:在Spring Boot应用中实现基于JWT的认证和授权

首先,添加相关依赖:

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

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

然后,实现UserDetails接口和自定义UserDetailsService:

public class UserDetailsImpl implements UserDetails {
  private Long id;
  private String username;
  private String password;
  private Collection<? extends GrantedAuthority> authorities;

  // getter and setter
}

public class UserDetailsServiceImpl implements UserDetailsService {
  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    // 根据用户名查找用户,并将其转换为UserDetailsImpl
  }
}

接着,配置Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Autowired
  private UserDetailsService userDetailsService;

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .authorizeRequests()
        .antMatchers("/api/v1/login").permitAll()
        .anyRequest().authenticated()
        .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and().addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
  }

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

  @Bean
  public JwtUtils jwtUtils() {
    // JwtUtils是自己实现的生成和解析JWT的工具类
    return new JwtUtils();
  }
}

编写JwtAuthenticationFilter:

public class JwtAuthenticationFilter extends OncePerRequestFilter {
  @Autowired
  private JwtUtils jwtUtils;

  @Override
  protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
    String token = jwtUtils.getToken(httpServletRequest);
    if (StringUtils.isNotBlank(token) && jwtUtils.validateToken(token)) {
      String username = jwtUtils.getUsernameFromToken(token);
      if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (jwtUtils.validateToken(token, userDetails)) {
          UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
          authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
          SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
      }
    }
    filterChain.doFilter(httpServletRequest, httpServletResponse);
  }
}

最后,为登录和注册接口添加认证和授权功能:

@RestController
@RequestMapping("/api/v1")
public class UserController {
  @Autowired
  private AuthenticationManager authenticationManager;

  @Autowired
  private UserDetailsService userDetailsService;

  @Autowired
  private JwtUtils jwtUtils;

  @PostMapping("/login")
  public String login(@RequestBody LoginRequest loginRequest) {
    Authentication authentication = authenticationManager.authenticate(
        new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
    SecurityContextHolder.getContext().setAuthentication(authentication);
    UserDetails userDetails = (UserDetails) authentication.getPrincipal();
    return jwtUtils.generateToken(userDetails);
  }

  @PostMapping("/register")
  public User register(@RequestBody RegistrationRequest registrationRequest) {
    // 处理注册请求
  }
}

示例2:如何在Mall电商平台中实现基于JWT的认证和授权

首先,添加以下依赖:

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

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

然后,定义UserDetailsImpl类:

public class UserDetailsImpl implements UserDetails {
  private Long id;
  private String username;
  private String password;
  private Collection<? extends GrantedAuthority> authorities;

  // getter and setter
}

接着,实现UserDetailsService,用于根据用户名查找用户:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
  @Autowired
  private UserService userService;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userService.getUserByUsername(username);
    if (user == null) {
      throw new UsernameNotFoundException("用户名不存在");
    }
    return new UserDetailsImpl(user.getId(), user.getUsername(), user.getPassword(),
            new ArrayList<>());
  }
}

配置Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Autowired
  private UserDetailsService userDetailsService;

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .authorizeRequests()
        .antMatchers("/user/login").permitAll()
        .antMatchers("/user/register").permitAll()
        .anyRequest().authenticated()
        .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and().addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
  }

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

  @Bean
  public JwtUtils jwtUtils() {
    return new JwtUtils();
  }
}

编写JwtAuthenticationFilter:

public class JwtAuthenticationFilter extends OncePerRequestFilter {
  @Autowired
  private JwtUtils jwtUtils;

  @Autowired
  private UserDetailsService userDetailsService;

  @Override
  protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
    String token = jwtUtils.getToken(httpServletRequest);
    if (StringUtils.isNotBlank(token) && jwtUtils.validateToken(token)) {
      String username = jwtUtils.getUsernameFromToken(token);
      if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (jwtUtils.validateToken(token, userDetails)) {
          UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
          authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
          SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
      }
    }
    filterChain.doFilter(httpServletRequest, httpServletResponse);
  }
}

最后,在用户登录接口中添加认证和授权功能:

@RestController
@RequestMapping("/user")
public class UserController {
  @Autowired
  private UserService userService;

  @Autowired
  private AuthenticationManager authenticationManager;

  @Autowired
  private JwtUtils jwtUtils;

  @PostMapping("/login")
  public String login(@RequestBody LoginRequest loginRequest) {
    Authentication authentication = authenticationManager.authenticate(
        new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
    SecurityContextHolder.getContext().setAuthentication(authentication);
    UserDetails userDetails = (UserDetails) authentication.getPrincipal();
    return jwtUtils.generateToken(userDetails);
  }

  @PostMapping("/register")
  public User register(@RequestBody RegistrationRequest registrationRequest) {
    // 处理注册请求
  }
}

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

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

相关文章

  • Spring Security全新版本使用方式

    下面是关于Spring Security全新版本使用方式的完整攻略: 什么是Spring Security? Spring Security是一个强大且可高度自定义的框架,用于身份验证和授权。它基于Servlet过滤器,可以轻松地将安全性添加到Web应用程序中。 如何使用Spring Security? 步骤一:添加Spring Security依赖 首先,…

    Java 2023年5月20日
    00
  • Spring Boot 单元测试JUnit的实践

    下面是关于“Spring Boot 单元测试JUnit的实践”的完整攻略: 一、为什么需要进行单元测试 单元测试是指对程序中的最小可测试单元进行检查和验证,确保每个单元都可以独立地并且正确地工作。而JUnit是Java中广泛使用的单元测试框架之一。 在实际开发中,进行单元测试可以帮助我们及时发现程序中的错误和bug,提高代码的健壮性和可靠性,同时也可以避免因…

    Java 2023年5月19日
    00
  • Java毕业设计之多用户宿舍管理系统的实现

    Java毕业设计之多用户宿舍管理系统的实现攻略 1. 需求分析 多用户宿舍管理系统需要实现如下功能:1. 根据管理员账号和密码登录系统;2. 管理员可以添加、查询、修改和删除学生信息;3. 管理员可以添加、查询、修改和删除宿舍信息;4. 管理员可以将学生分配到某个宿舍;5. 学生可以使用学生账号和密码登录系统;6. 学生可以查询自己的宿舍信息,并进行相关操作…

    Java 2023年5月24日
    00
  • Java多线程编程小实例模拟停车场系统

    Java多线程编程小实例模拟停车场系统攻略 概述 本实例主要使用Java多线程编程,模拟停车场系统,包括车辆入场、出场、停车等基本功能。该系统采用面向对象思想,通过多线程程序的编写,模拟实现停车场系统的相关功能。 实现步骤 设计车辆类 首先要设计车辆类,包括车牌号、车型、停车时间、出场时间等属性。以下是车辆类的示例代码: class Car { privat…

    Java 2023年5月19日
    00
  • tomcat 启动时卡住问题排查及解决方法

    Tomcat 启动时卡住问题排查及解决方法 问题现象 在启动 Tomcat 时,控制台输出日志较少,没有显示任何正在启动的进程,且进程状态一直卡在某个进程上,无法启动成功。 问题原因 防火墙限制 在部分云服务器或者企业内部网络环境下,会有防火墙限制,导致 Tomcat 无法正常启动。可以通过关闭防火墙或者添加相应的端口规则来解决。 JVM 堆栈调整不合理 如…

    Java 2023年6月2日
    00
  • java加载properties文件的六种方法总结

    以下是讲解“java加载properties文件的六种方法总结”的完整攻略。 一、背景 在Java应用中经常会使用配置文件properties来存储一些固定的配置信息,方便程序在运行时读取。那么在Java中如何加载properties文件呢?本文将总结6种Java加载properties文件的方法。 二、直接使用Java代码加载 直接使用Java代码加载pr…

    Java 2023年5月20日
    00
  • Java对MySQL数据库进行连接、查询和修改操作方法

    关于“Java对MySQL数据库进行连接、查询和修改操作方法”的完整攻略,我们可以以下列步骤进行: 1. 下载MySQL的JDBC驱动器 Java需要使用MySQL连接器(JDBC驱动器)才能连接MySQL服务器。你可以从MySQL官网上找到驱动器并下载。 下载的链接是:https://dev.mysql.com/get/Downloads/Connecto…

    Java 2023年5月20日
    00
  • Java实现有限状态机的推荐方案分享

    Java 实现有限状态机的推荐方案分享 有限状态机(Finite State Machine,FSM)是一种计算模型,它可以使用有限个状态和它们之间的转移,来描述一个系统在不同状态下的行为。在软件开发中,常常需要使用有限状态机来解决复杂问题,比如网络协议解析、报文处理、游戏逻辑等。 本文将介绍 Java 实现有限状态机的一些推荐方案,并提供了两条示例说明,供…

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