SpringSecurity构建登录模块

引入依赖

引入依赖(实现拦截):

java 复制代码
<!--引入springsecurity的依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- JWT相关 -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
</dependency>

自定义登录逻辑

实现框架默认的UserDetailsService 自定义登录逻辑:

java 复制代码
@Service
public class MyDetailsService implements UserDetailsService {

    @Resource
    private SysUserMapper sysUserMapper;

    // 自定义认证逻辑
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1.构造查询条件
        QueryWrapper<SysUserDO> wrapper = new QueryWrapper<SysUserDO>().eq("user_account", username);
        // 2.查询用户
        SysUserDO user = sysUserMapper.selectOne(wrapper);
        // 3.封装为UserDetails对象
        UserDetails userDetails = User
                .withUsername(user.getUserName())
                .password(user.getUserPassword())
                .authorities("admin")
                .build();
        // 4.返回封装好的UserDetails对象
        return userDetails;
    }
}

配置主配置类

配置主配置类(实现鉴权):

java 复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyDetailsService myDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
//        return new BCryptPasswordEncoder();
          return NoOpPasswordEncoder.getInstance();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myDetailsService)
                .passwordEncoder(passwordEncoder());
//        auth.inMemoryAuthentication()
//                .withUser("user").password("{noop}password").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .formLogin()
                .successHandler(new LoginAuthenticationSuccessHandler())
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                //跨站点请求伪造
                .csrf()
                .disable()
                .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
        ;
    }

    /** 拦截器 **/
    @Bean
    public TokenAuthenticationFilter tokenAuthenticationFilter() {
        return new TokenAuthenticationFilter();
    }
}

配置鉴权成功处理类

配置鉴权成功处理类(AuthenticationSuccessHandler)实现返回token:

java 复制代码
@Component
@Slf4j
public class LoginAuthenticationSuccessHandler implements AuthenticationSuccessHandler {


    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();

        // 生成 token
        String username = userDetails.getUsername();
        String token = JwtUtil.createJWT(UUID.randomUUID().toString(), userDetails.getUsername(),
                3600L * 1000 * 6);

        // 返回结果
        log.info("==> 用户认证成功, username: {}, token: {}", username, token);

        // 将token存储到HTTP响应头中
        response.setHeader(HttpConstant.X_ACCESS_TOKEN, token);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);

        // 返回响应体
        PrintWriter writer = response.getWriter();

        //构造响应
        Map<String, Object> stringObjectMap = BeanUtil.beanToMap(userDetails);
        stringObjectMap.put("token",token);

        writer.write(new ObjectMapper().writeValueAsString(Result.buildSuccess(stringObjectMap)));
        writer.flush();
        writer.close();
    }
}

配置Filter

配置Filter实现token:

java 复制代码
@Slf4j
public class TokenAuthenticationFilter extends OncePerRequestFilter {

    @Resource
    private MyDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        ObjectMapper objectMapper = new ObjectMapper();
        response.setCharacterEncoding("UTF-8");
        String token = request.getHeader(HttpConstant.X_ACCESS_TOKEN);
        String userName = null;
        if (StringUtils.isNotBlank(token)) {
            try {
                userName = JwtUtil.parseJWT(token).getSubject();
            } catch (Exception e) {
                response.getWriter().write(objectMapper.writeValueAsString(Result.buildError("token校验失败!")));
                return;
            }
            if (StringUtils.isNotBlank(userName)) {
                // && Objects.isNull(SecurityContextHolder.getContext().getAuthentication())

                UserDetails userDetails = null;
                userDetails = userDetailsService.loadUserByUsername(userName);

                // 将用户信息存入 authentication ThreadLocal,方便后续校验
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null,
                        userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                // 用于鉴权
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        // 继续执行下一个过滤器
        filterChain.doFilter(request, response);
    }
}
相关推荐
DsirNg2 天前
凭证不是登录态:从攻击面重做浏览器认证设计
oauth·xss·csrf·token·cookie·认证授权·web 安全
YoanAILab2 天前
大语言模型基础:Token、Embedding、Transformer、KV Cache 与 RAG
语言模型·transformer·embedding·token·rag
小七-七牛开发者7 天前
拆解 dsh 系列:从源码和版本变化看 DeepSeek Harness 的设计取舍
ai·大模型·claude·token·工作流·skill·claudecode·ai coding
XLYcmy7 天前
PDF论文处理器 - 完整使用指南
pdf·llm·json·agent·token·csv·dify
杨云龙UP7 天前
Linux 下 MySQL 常用登录方式及 Socket 排查指南
linux·运维·数据库·mysql·登录·xtrabackup·主从复制
guwentian7 天前
不用显卡也能跑大模型?GGUF 量化与 llama.cpp 本地推理实战
大模型·token·gguf
小七-七牛开发者8 天前
Agent 小知识 | Skill 的设计与生命周期:从工具接口到能力模块
ai·大模型·agent·token·工作流·claudecode·ai coding
孔明click338 天前
不想写代码,但想要集成一个登录页面?Sa-Token-Quick-Login 帮你实现!
java·sa-token·开源·springboot·登录·权限·权限认证
yuyuyui9 天前
DOTNET 鉴权系列- JWT 会话撤销与主动登出
jwt·.net core·token·主动登出·会话撤销