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);
    }
}
相关推荐
知无不研3 天前
调用模型的API接口与Token详谈
ai·agent·token·api接口
XLYcmy4 天前
大语言模型(LLM)核心技术梳理:从词元化到 RAG 的工程实践
自然语言处理·prompt·embedding·token·cot·tokenization·上下文工程
szephyr4 天前
前端鉴权实战:Token 存哪、怎么刷新、怎么防 XSS 与 CSRF
鉴权·xss·csrf·jwt·token
csdn_aspnet5 天前
.NetCore Webapi 接口验证请求来源
.netcore·ip·token·签名·webapi·cors·sign
丿Wayne5 天前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
花北城6 天前
【C#底层库】access_token授权鉴权验证
c#·鉴权·token·授权
七夜zippoe6 天前
Agent 上下文工程:Token 管理、上下文压缩与分层记忆设计
ai·agent·token·上下文压缩·分层记忆
九章云极DataCanvas7 天前
让大模型少做重复计算 九章云极开源分布式KV Cache系统DingoCache
人工智能·开源·token·九章智算云
SoStraw8 天前
从零接入 webrpc:按这份最小清单跑通双端,再写业务
sdk·p2p·入门·token·webrpc·opensession·senddata
kolyle9 天前
万级 QPS 下的 Token 分发系统架构:从 0 到 1 跑通 AI 时代的“水电煤“
开发语言·人工智能·系统架构·token·qps·极智词元·大模型私有化部署