SpringBoot整合SpringSecurit(二)通过token进行访问

在文章:SpringBoot整合SpringSecurit(一)实现ajax的登录、退出、权限校验-CSDN博客

里面,使用的session的方式进行保存用户信息的,这一篇文章就是使用token的方式。

在其上进行的改造,可以先看SpringBoot整合SpringSecurit(一)实现ajax的登录、退出、权限校验-CSDN博客,再看这个就比较好了。

1、新建过滤器,将通过token查询到的用户信息存入到security中

复制代码
package com.example.springboot.security.demo.filter;

import com.example.springboot.security.demo.controller.LoginController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * 将用户信息存入security中
 */
@Slf4j
@Component
public class AuthFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 比如请求头中有个header叫token,放置了认证后的请求头
        String token = request.getHeader("token");
        log.info("用户token:{}", token);
        if (StringUtils.hasText(token)) {
            // 验证token是否已经登录了的用户的token,用户的token临时放在了LoginController
            UserDetails userDetails = LoginController.TOKEN_USERNAME.get(token);
            if (Objects.nonNull(userDetails)) {
                // 有,表示token是对的,设置线程上下文认证信息,然后访问其他资源时,security就会放行
                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }
        filterChain.doFilter(request, response);
    }
}

2、修改security的配置

复制代码
/**
     * 密码加密方式
     * //使用BCrypt进行密码加密校验
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


/**
     * 2.0配置,security通过token访问,不通过session访问
     * @param http
     * @throws Exception
     */
    @Resource
    private AuthFilter authFilter;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();//禁用CSRF控制,即spring security不再限制CSRF,即跨越访问

        http
                .authorizeRequests()
                .antMatchers("/static/**").permitAll()//不需要登录认证就可以访问,静态资源等不需要验证
                .antMatchers("/login").permitAll() // 允许任何人访问登录接口
                .anyRequest().authenticated();//其他路径必须验证身份

        http
                .sessionManagement(sessionManager -> sessionManager.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); //不再管理session

        // 设置用户访问前filter
        http.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class);

        http
                .formLogin()
                .loginPage("/login-view.html")//自定义登录页面路径,加载登录的html页面
                .successHandler(userLoginAuthenticationSuccessHandler)//验证成功处理
                .failureHandler(userLoginAuthenticationFailureHandler)//验证失败处理
                .permitAll();//登录页面无需设置验证

        http
                .logout()
                .logoutUrl("/logout")//登出路径
                .logoutSuccessHandler(userLogoutSuccessHandler)//登出处理
                .permitAll()//不需要身份认证
                .and()
                .exceptionHandling().accessDeniedHandler(userAuthenticationAccessDeniedHandler);//无权限时的处理
    }

3、修改登录方法,后端获取到账号、密码后,根据账号,查询到用户信息,在校验密码,如果密码成功,就生成token,并且把token放在内存或者redis中就完成了

复制代码
/**
     * 简单的存放用户登录认证成功信息的地方
     */
    public final static Map<String, UserDetails> TOKEN_USERNAME = new HashMap<>();
    @Resource
    private UserDetailsServiceImpl userDetailsService;
    /**
     * SecurityConfig中配置的密码加密
     */
    @Resource
    private PasswordEncoder passwordEncoder;

    /**
     * 登录认证,获得token
     * @param account 登录账号
     * @param password 密码
     * @return 认证token
     */
    @ResponseBody
    @PostMapping("/login")
    public JsonData login(String account, String password) {
        JsonData jsonData = null;
        //根据账号,查询用户信息
        UserDetails userDetails = userDetailsService.loadUserByUsername(account);
        if (userDetails == null) {
            jsonData = new JsonData(401,"用户名不存在");
            return jsonData;
        }
        //密码校验
        if(!passwordEncoder.matches(password,userDetails.getPassword())) {
            jsonData = new JsonData(401,"用户或密码错误");
            return jsonData;
        }
        // 认证成功发个token,返回给前端
        String token = UUID.randomUUID().toString();
        TOKEN_USERNAME.put(token, userDetails);
        System.out.println("token:" + token);
        jsonData = new JsonData(200,token);
        return jsonData;
    }

4、测试

4.1、获取token

4.2、通过token查询信息

相关推荐
张哈大6 分钟前
【 Redis | 实战篇 秒杀优化 】
java·数据库·redis·笔记·缓存
低维歌者12 分钟前
python训练营day27
java·开发语言·python
大帅不是我21 分钟前
Python多进程编程执行任务
java·前端·python
Fu_lucas25 分钟前
Python Logging 模块完全指南
开发语言·python
Eiceblue27 分钟前
Python 在Excel单元格中应用多种字体样式
开发语言·vscode·python·pycharm·excel
purrrew1 小时前
【Java ee初阶】jvm(3)
java·jvm
Hello World......2 小时前
互联网大厂Java面试:从Spring到微服务的全面探讨
java·spring boot·spring cloud·微服务·面试·技术栈·互联网大厂
拾贰_C3 小时前
【SpringBoot】MyBatisPlus(MP | 分页查询操作
java·spring boot·后端·spring·maven·apache·intellij-idea
猛踹瘸子那条好腿の3 小时前
Spring-boot初次使用
java·springboot
shykevin5 小时前
python开发Streamable HTTP MCP应用
开发语言·网络·python·网络协议·http