springboot Security 自定义密码校验

第一步 实现 PasswordEncoder 接口类

package com.minex.web.devicealarm.aop.configure;

import com.minex.common.util.MD5Util;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
public class CustomPasswordEncoder implements PasswordEncoder {

    @Resource
    private MD5Util md5Util;

    // 加密密码(通常用于新密码存储)
    @Override
    public String encode(CharSequence rawPassword) {
        // 示例:使用 MD5 加密(不推荐,仅作演示)
        return md5Util.getMD5ofStrSub(rawPassword.toString());
    }

    // 校验密码(将用户输入的明文密码与加密后的密码比对)
    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        // 示例:校验逻辑(兼容旧系统 MD5 加密)
        return md5Util.getMD5ofStrSub(rawPassword.toString()).equals(encodedPassword);
    }
}

 

第二步 在继承了 WebSecurityConfigurerAdapter 类中配置 encodedPassword

package com.minex.web.devicealarm.aop.configure;

import com.minex.filter.JwtAuthenticationTokenFilter;
import com.minex.handler.AuthenticationEntryPointHandler;
import com.minex.handler.LogoutSuccessHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter;

import javax.annotation.Resource;
/**
 * @Author: lorry.luo
 * @time: 2024-10-10 13-52
 * @Description spring security 配置
 * @Version 1.0.0
 */
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    /**
     * Security configuration
     *
     * @since 3.0.0
     */
    public SecurityConfiguration() {
        log.info("init SecurityConfiguration");
    }

    /**
     * 自定义用户认证逻辑
     */
    @Resource
    private UserDetailsService userDetailsService;

    /**
     * 跨域过滤器
     */
    @Resource
    private CorsFilter corsFilter;

    /**
     * 解决 无法直接注入 AuthenticationManager
     *
     * @return authentication manager
     * @throws Exception exception
     * @since 3.0.0
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * anyRequest          |   匹配所有请求路径
     * access              |   SpringEl 表达式结果为 true 时可以访问
     * anonymous           |   匿名可以访问
     * denyAll             |   用户不能访问
     * fullyAuthenticated  |   用户完全认证可以访问(非 remember-me 下自动登录)
     * hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问
     * hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问
     * hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问
     * hasIpAddress        |   如果有参数,参数表示 IP 地址,如果用户 IP 和参数匹配,则可以访问
     * hasRole             |   如果有参数,参数表示角色,则其角色可以访问
     * permitAll           |   用户可以任意访问
     * rememberMe          |   允许通过 remember-me 登录的用户访问
     * authenticated       |   用户登录后可访问
     *
     * @param httpSecurity http security
     * @throws Exception exception
     * @since 3.0.0
     */
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // CSRF 禁用,因为不使用 session
                .csrf().disable()
                // 认证失败处理类
                .exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPointHandler()).and()
                // 基于 token,所以不需要 session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                // 过滤请求
                .authorizeRequests()
                // 对于登录 login 验证码 captchaImage 允许匿名访问
                .antMatchers("/login", "/captcha", "/openApi/**", "/*.html").anonymous()
                .antMatchers(
                        HttpMethod.GET,
                        "/*.html",
                        "/**/*.html",
                        "/**/*.css",
                        "/api/**",
                        "/**/*.js"
                ).permitAll()
                .antMatchers("/profile/**").anonymous()
                .antMatchers("/common/download**").anonymous()
                .antMatchers("/common/download/classPath**").anonymous()
                .antMatchers("/common/download/resource**").anonymous()
                .antMatchers("/swagger-ui.html").anonymous()
                .antMatchers("/doc.html").anonymous()
                .antMatchers("/swagger-resources/**").anonymous()
                .antMatchers("/webjars/**").anonymous()
                .antMatchers("/*/api-docs").anonymous()
                .antMatchers("/druid/**").anonymous()
                .antMatchers("/xrebel/**").anonymous()
                .antMatchers("/weather/**").anonymous()
                .antMatchers("/analysis/**").permitAll()
                .antMatchers("/thirdData/**").permitAll()
                .antMatchers("/home/page/**").permitAll()
                .antMatchers("/websocket/**").permitAll()
                .antMatchers("/monitor/server/**").permitAll()
                .antMatchers("/cnesus/**").permitAll()
                .antMatchers("/curveAnalysis/**").permitAll()
                .antMatchers("/actuator/**").permitAll()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated()
                .and()
                .headers().frameOptions().disable();
        httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(new LogoutSuccessHandler());
        // 添加 JWT filter
        httpSecurity.addFilterBefore(new JwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        // 添加 CORS filter
        httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
        httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
    }

    /**
     * 强散列哈希加密实现
     *
     * @return the b crypt password encoder
     * @since 3.0.0
     */
    @Bean
    public CustomPasswordEncoder cryptPasswordEncoder() {
        return new CustomPasswordEncoder();
    }

    /**
     * 身份认证接口
     *
     * @param auth auth
     * @throws Exception exception
     * @since 3.0.0
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(cryptPasswordEncoder());
    }

}

 

posted @ 2025-05-19 18:11  官萧何  阅读(119)  评论(0)    收藏  举报