SpringSecurity 自定义扩展

SpringSecurity 自定义扩展

![[

1、定义filter

import com.lzy.wzy.token.MyUsernamePasswordToken;
import com.lzy.wzy.utils.IpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    private final Logger log= LoggerFactory.getLogger(MyUsernamePasswordAuthenticationFilter.class);
    private String usernameParameter = "username";
    private String passwordParameter = "password";
    private SessionRegistry sessionRegistry;
    private boolean postOnly = true;

    public MyUsernamePasswordAuthenticationFilter() {
        super(new AntPathRequestMatcher("/api/doLogin", "POST"));
    }
    public MyUsernamePasswordAuthenticationFilter(SessionRegistry sessionRegistry){
        super(new AntPathRequestMatcher("/api/doLogin", "POST"));
        this.sessionRegistry=sessionRegistry;
    }

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (this.postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        } else {
            String username = this.obtainUsername(request);
            username = username != null ? username : "";
            username = username.trim();
            String password = this.obtainPassword(request);
            password = password != null ? password : "";
            log.info("IpUtil.getIpAddr(request) {}",IpUtil.getIpAddr(request));
            MyUsernamePasswordToken authRequest = new MyUsernamePasswordToken(username, password);
            sessionRegistry.registerNewSession(request.getSession().getId(),authRequest.getPrincipal());
            this.setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }
    }

    @Nullable
    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(this.passwordParameter);
    }

    @Nullable
    protected String obtainUsername(HttpServletRequest request) {
        return request.getParameter(this.usernameParameter);
    }


    protected void setDetails(HttpServletRequest request, MyUsernamePasswordToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

    public void setUsernameParameter(String usernameParameter) {
        Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
        this.usernameParameter = usernameParameter;
    }

    public void setPasswordParameter(String passwordParameter) {
        Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
        this.passwordParameter = passwordParameter;
    }


    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    public final String getUsernameParameter() {
        return this.usernameParameter;
    }

    public final String getPasswordParameter() {
        return this.passwordParameter;
    }
}

2、定义所需的AuthenticationToken

import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Collection;

public class MyUsernamePasswordToken extends AbstractAuthenticationToken {
    private static final long serialVersionUID = 540L;
    private final Object principal;
    private Object credentials;
    private String uri;

    public MyUsernamePasswordToken(Object principal, Object credentials) {
        super(null);
        this.principal = principal;
        this.credentials = credentials;
        this.setAuthenticated(false);
    }
    public MyUsernamePasswordToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }
    public MyUsernamePasswordToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities,String uri) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        this.uri=uri;
        super.setAuthenticated(true);
    }

    public String getUri() {
        return uri;
    }

    public Object getCredentials() {
        return this.credentials;
    }

    public Object getPrincipal() {
        return this.principal;
    }

    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        Assert.isTrue(!isAuthenticated, "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        super.setAuthenticated(false);
    }

    public void eraseCredentials() {
        super.eraseCredentials();
        this.credentials = null;
    }

3、定义provider

import com.lzy.wzy.config.MyPasswordEncoder;
import com.lzy.wzy.exception.DepartmentSelectionException;
import com.lzy.wzy.model.UserBean;
import com.lzy.wzy.service.imp.UserServiceImp;
import com.lzy.wzy.token.MyUsernamePasswordToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class MyAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private UserServiceImp userServiceImp;

    @Autowired
    private MyPasswordEncoder myPasswordEncoder;


    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = (String) authentication.getCredentials();
        UserBean user = (UserBean) userServiceImp.loadUserByUsername(username);
        if (!user.isEnabled()) {
            throw new DisabledException("该账户已被禁用,请联系管理员");

        } else if (!user.isAccountNonLocked()) {
            throw new LockedException("该账号已被锁定");

        } else if (!user.isAccountNonExpired()) {
            throw new AccountExpiredException("该账号已过期,请联系管理员");

        } else if (!user.isCredentialsNonExpired()) {
            throw new CredentialsExpiredException("该账户的登录凭证已过期,请重新登录");
        }
//        if (!checkUtils.isPasswordOk(password)) {
//            throw new BadCredentialsException("密码格式有误!");
//        }
        //验证密码
        if (!myPasswordEncoder.matches(password, user.getPassword())) {
            throw new BadCredentialsException("输入密码错误!");
        }
        return new MyUsernamePasswordToken(user, password, user.getAuthorities());
    }


    @Override
    public boolean supports(Class<?> authentication) {
        // 判断 authentication 是不是 AuthenticationToken 的子类或子接口
        return MyUsernamePasswordToken.class.isAssignableFrom(authentication);
    }
}

4、定义jwt转换器,以及token生成配置

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.annotation.Resource;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class JwtTokenAuthConfig {
    @Autowired
    private MyTokenEnhancer myTokenEnhancer;

    @Autowired
    private UserDetailsService userDetailsService;


    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Bean(name = "jwtTokenStoreAuth")
    public TokenStore jwtTokenStoreAuth(){
        return new JwtTokenStore(jwtAccessTokenConverterAuth());
    }


    @Bean("redisTokenStore")
    public RedisTokenStore redisTokenStore(RedisConnectionFactory redisConnectionFactory){
        RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
        redisTokenStore.setPrefix("auth_token:");
        return redisTokenStore;
    }

    @Bean(name = "jwtAccessTokenConverterAuth")
    public JwtAccessTokenConverter jwtAccessTokenConverterAuth(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        DefaultAccessTokenConverter defaultAccessTokenConverter = new DefaultAccessTokenConverter();
        DefaultUserAuthenticationConverter userAuthenticationConverter = new DefaultUserAuthenticationConverter();
        userAuthenticationConverter.setUserDetailsService(userDetailsService);
        defaultAccessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
        jwtAccessTokenConverter.setAccessTokenConverter(defaultAccessTokenConverter);
        //jwtAccessTokenConverter.setSigningKey("wylwzy");
        ClassPathResource resource = new ClassPathResource("oauth-jwt.jks");
        KeyStoreKeyFactory keyFactory = new KeyStoreKeyFactory(resource, "wzy666".toCharArray());
        KeyPair keyPair = keyFactory.getKeyPair("wzy");
        jwtAccessTokenConverter.setKeyPair(keyPair);
        return jwtAccessTokenConverter;
    }
    /**
     * 配置令牌管理
     */
    @Bean
    public AuthorizationServerTokenServices authorizationServerTokenServices(ClientDetailsService clientDetailsService) {
        DefaultTokenServices service = new DefaultTokenServices();
        service.setClientDetailsService(clientDetailsService);
        service.setSupportRefreshToken(true);
        service.setReuseRefreshToken(true);
        service.setTokenStore(jwtTokenStoreAuth());
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> list=new ArrayList<>();
        list.add(myTokenEnhancer);
        list.add(jwtAccessTokenConverterAuth());
        tokenEnhancerChain.setTokenEnhancers(list);
        service.setTokenEnhancer(tokenEnhancerChain);
        return service;
    }

}
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

@Configuration
@Slf4j
public class JwtTokenReConfig {

    @Bean(name = "jwtTokenStoreRe")
    public TokenStore jwtTokenStoreRe() {
        return new JwtTokenStore(jwtAccessTokenConverterRe());
    }

    @Bean(name = "jwtAccessTokenConverterRe")
    public JwtAccessTokenConverter jwtAccessTokenConverterRe() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        //jwtAccessTokenConverter.setSigningKey("wylwzy");
        jwtAccessTokenConverter.setVerifierKey(getPublicKey());
        return jwtAccessTokenConverter;
    }

    private String getPublicKey() {
        ClassPathResource resource = new ClassPathResource("publickey.txt");
        try (InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
             BufferedReader br = new BufferedReader(inputStreamReader)) {
            return br.lines().collect(Collectors.joining("\n"));
        } catch (IOException ioe) {
            return null;
        }
    }
}

5、定义认证成功handler

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lzy.wzy.mapper.UserMapper;
import com.lzy.wzy.model.UserBean;
import com.lzy.wzy.result.Response;
import com.lzy.wzy.result.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private final static String CLIENT_ID="clientapp";
    private final static String CLIENT_SECRET="$2a$10$nAwPWghTj2lTSG1yT2MXJu8zbIHW23UyG9wh5KGROnztQqFnJpvLS";
    private final static String GRANT_TYPE="password";
    private ClientDetails clientDetails;
    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private AuthorizationServerTokenServices authorizationServerTokenServices;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ObjectMapper objectMapper;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        log.info("登录成功");
        if (null == clientDetails) {
            log.info("查询 client info");
            clientDetails = clientDetailsService.loadClientByClientId(CLIENT_ID);
            if (null == clientDetails) {
                throw new UnapprovedClientAuthenticationException("clientId不存在" + CLIENT_ID);
            }
        }
        if (!CLIENT_SECRET.equals(clientDetails.getClientSecret())){
            throw new UnapprovedClientAuthenticationException("clientSecret不匹配" + clientDetails.getClientSecret());
        }else {
            Map<String, String> map=new HashMap<>();
            UserBean user = (UserBean) authentication.getPrincipal();
            map.put("username",user.getUsername());
            map.put("password",user.getPassword());
            //更新最后一次登录时间
            Map<String,Object> userMap=new HashMap<>();
            userMap.put("userUuid",user.getUserUuid());
            userMap.put("timeOnline", LocalDateTime.now());
            userMapper.updateOnlineTime(userMap);

            TokenRequest tokenRequest = new TokenRequest(map,CLIENT_ID,clientDetails.getScope(),GRANT_TYPE);

            OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);

            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request,authentication);
            OAuth2AccessToken accessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
//            System.out.println(accessToken.getValue());
            String token = authorizationServerTokenServices.refreshAccessToken(accessToken.getRefreshToken().getValue(), tokenRequest).getValue();
            System.out.println(token);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.write(objectMapper.writeValueAsString(new Response<>(ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getMsg(), accessToken.getValue())));
            writer.flush();
        }
    }
}

6、将自定义的配置加入到springsecurity的配置

import com.lzy.wzy.filter.MyUsernamePasswordAuthenticationFilter;
import com.lzy.wzy.handle.CustomAuthenticationFailureHandler;
import com.lzy.wzy.handle.CustomAuthenticationSuccessHandler;
import com.lzy.wzy.provider.MyAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy;
import org.springframework.security.web.session.ConcurrentSessionFilter;
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy;
import org.springframework.stereotype.Component;

@Component
public class MyAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {


    @Autowired
    private MyAuthenticationProvider myAuthenticationProvider;

    @Autowired
    private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

    @Autowired
    private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Autowired
    private SessionRegistry sessionRegistry;


    @Autowired
    private SessionInformationExpiredStrategy sessionInformationExpiredStrategy;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        MyUsernamePasswordAuthenticationFilter authenticationFilter = new MyUsernamePasswordAuthenticationFilter(sessionRegistry);
        authenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
        authenticationFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
        authenticationFilter.setAuthenticationFailureHandler(customAuthenticationFailureHandler);
        authenticationFilter.setSessionAuthenticationStrategy(new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry));
        http.addFilterBefore(new ConcurrentSessionFilter(sessionRegistry, sessionInformationExpiredStrategy), ConcurrentSessionFilter.class);
        http.authenticationProvider(myAuthenticationProvider).addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);
        http.sessionManagement()//只允许一个用户登录,如果同一个账户两次登录,那么第一个账户将被踢下线,跳转到登录页面
                .invalidSessionUrl("/index/none/toLogin")
                .maximumSessions(1)
                .sessionRegistry(sessionRegistry)
                .expiredUrl("/index/none/toLogin");
    }
}

7、将配置应用WebSecurity中

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

    http.apply(myAuthenticationSecurityConfig);
    http.cors();
    http.headers().frameOptions().disable();
    http.authorizeRequests()
            .requestMatchers(CorsUtils::isPreFlightRequest).permitAll();
    //允许匿名访问所有接口
    http.csrf().disable();
    http.authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .loginPage("/index/none/toLogin")
            .permitAll()
            .and()
            .logout()
            .logoutSuccessHandler(customLogoutSuccessHandler)
            .permitAll();
}

8、tokenenhancer token增强器

import com.lzy.wzy.model.UserBean;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class MyTokenEnhancer implements TokenEnhancer {
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
        Map<String,Object> map=new HashMap<>();
        UserBean userBean = (UserBean)oAuth2Authentication.getUserAuthentication().getPrincipal();
        map.put("username",userBean.getUsername());
        map.put("userUuid",userBean.getUserUuid());
        map.put("lzy",userBean.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
        ((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(map);
        return oAuth2AccessToken;
    }
}
OAuth2AccessToken oAuth2AccessToken;
try {
    oAuth2AccessToken = jwtTokenStoreRe.readAccessToken(token);
    if (oAuth2AccessToken.isExpired()) {
        log.info("token 已过期");
        String refresh = request.getHeader("refresh");
        OAuth2RefreshToken oAuth2RefreshToken = jwtTokenStoreRe.readRefreshToken(refresh);
        System.out.println(jwtTokenStoreRe.readAccessToken(oAuth2RefreshToken.getValue()));
        expiredTokenMono(response);
        return;
    }
    Map<String, Object> additionalInformation = oAuth2AccessToken.getAdditionalInformation();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pt0jlB3L-1687679515921)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230625151038764.png)]

对于bms认证头生成方法是Base64.getEncoder().encodeToString(“xx:xx”.getBytes())

https://blog.csdn.net/lucktomcat/article/details/125555678

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Security提供了多种登录方式的支持,可以使用表单登录、Basic认证、OAuth2等方式进行身份验证。如果需要自定义多种登录方式,可以按照以下步骤进行: 1. 实现自定义的AuthenticationProvider AuthenticationProvider是Spring Security的一个核心接口,用于实现身份验证逻辑。通过实现自定义的AuthenticationProvider,可以实现多种不同的身份验证方式。 例如,可以实现一个LDAPAuthenticationProvider,用于基于LDAP的身份验证,或者实现一个SmsCodeAuthenticationProvider,用于基于短信验证码的身份验证。 2. 配置多个AuthenticationProvider 在Spring Security配置文件中,可以通过配置多个AuthenticationProvider来支持多种登录方式。例如,可以同时配置一个基于表单登录的AuthenticationProvider和一个基于OAuth2的AuthenticationProvider。 3. 实现自定义的AuthenticationFilter AuthenticationFilter是Spring Security用于处理身份验证请求的过滤器。通过实现自定义的AuthenticationFilter,可以实现多种不同的身份验证方式。 例如,可以实现一个基于短信验证码的AuthenticationFilter,用于处理短信验证码登录请求。 4. 配置多个AuthenticationFilter 在Spring Security配置文件中,可以通过配置多个AuthenticationFilter来支持多种登录方式。例如,可以同时配置一个基于表单登录的AuthenticationFilter和一个基于短信验证码的AuthenticationFilter。 总的来说,实现多种登录方式的关键在于实现自定义的AuthenticationProvider和AuthenticationFilter,并在Spring Security配置文件中进行配置。 ### 回答2: Spring Security 提供了多种自定义登录方式的选项。以下是一些常见的方法: 1. 自定义用户名密码登录:可以使用 Spring Security 的表单登录功能,通过配置用户名和密码的输入框,实现用户名密码登录功能。 例如,可以通过配置 `formLogin()` 方法来实现: ```java protected void configure(HttpSecurity http) throws Exception { http .formLogin() .loginPage("/login") .usernameParameter("username") .passwordParameter("password") .defaultSuccessUrl("/home") .permitAll(); } ``` 2. 自定义第三方登录:可以使用 Spring Security OAuth2 来实现第三方登录,例如使用 Facebook、Google 或 Github 等社交媒体的账号进行登录。 Spring Security OAuth2 提供了很多集成第三方认证的实例代码,可以根据具体的需求进行自定义。 3. 自定义手机号码登录:可以通过继承 Spring Security 的 `AbstractAuthenticationProcessingFilter` 类来实现自定义手机号码登录。 可以在自定义的过滤器中验证手机号码,并进行认证逻辑。 4. 自定义单点登录(SSO):可以通过集成 Spring Security 的 `AuthenticationProvider` 接口来实现自定义的单点登录认证。 可以通过实现该接口的 `authenticate()` 方法来处理单点登录的逻辑。 这些只是一些常见的自定义登录方式的示例,根据具体的需求,可以结合 Spring Security 提供的各种功能和扩展点,灵活地进行自定义实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值