泉城打码师 2023-06-28 16:16 采纳率: 0%
浏览 80
已结题

关于#SpringSecurity#的问题,如何解决?

SpringSecurity6.1

自己重写UsernamePasswordAuthenticationFilter

package com.hw.example.admin.config.security.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hw.example.admin.config.security.domain.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
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.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.IOException;

/**
 * @author : guanzheng
 * @date : 2023/6/26 15:17
 */
public class JsonLoginFilter extends UsernamePasswordAuthenticationFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //获取请求头,据此判断请求参数类型
        String contentType = request.getContentType();
        if (MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType) || MediaType.APPLICATION_JSON_UTF8_VALUE.equalsIgnoreCase(contentType)) {
            //说明请求参数是 JSON
            if (!request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
            }
            String username = null;
            String password = null;
            try {
                //解析请求体中的 JSON 参数
                User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
                username = user.getUsername();
                username = (username != null) ? username.trim() : "";
                password = user.getPassword();
                password = (password != null) ? password : "";
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //构建登录令牌
            UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username,
                    password);
            // Allow subclasses to set the "details" property
            setDetails(request, authRequest);
            //执行真正的登录操作
            Authentication auth = this.getAuthenticationManager().authenticate(authRequest);

            SecurityContextHolder.getContext().setAuthentication(auth);

            return auth;
        }
        return super.attemptAuthentication(request,response);
    }
}

package com.hw.example.admin.config.security;

import com.hw.example.admin.config.security.filter.JsonLoginFilter;
import com.hw.example.admin.config.security.handler.LoginFailureHandler;
import com.hw.example.admin.config.security.handler.LoginSuccessHandler;
import com.hw.example.admin.config.security.handler.LogoutHandler;
import com.hw.example.admin.config.security.handler.MyPasswordEncoder;
import com.hw.example.admin.config.security.service.UserDetailServiceImpl;
import com.hw.example.common.util.http.HttpUtil;
import com.hw.example.common.web.component.R;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.IOException;

/**
 * @author : guanzheng
 * @date : 2023/6/25 9:03
 */
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Autowired
    UserDetailServiceImpl userDetailService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        //认证请求配置
        http.authorizeHttpRequests()
                //允许匿名访问的地址,写在最前边
                .requestMatchers("/hello").permitAll()
                //其他请求必须认证才能访问
                .anyRequest().authenticated()
                .and()
                .exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
                    @Override
                    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
                        HttpUtil.writeResponse(response, R.ok("未登录"));
                    }
                })
                .and()
                //登录表单配置
                .formLogin()
                //登录表单的用户名name
//                .usernameParameter("username")
                //登录表单的密码name
//                .passwordParameter("password")
                .and()
                .logout()
                //退出登录的url
//                .logoutUrl("/logout")
                .logoutSuccessHandler(new LogoutHandler())
                //清除session
//                .invalidateHttpSession(true)
                //清除认证信息
//                .clearAuthentication(true)
                .and()
                //关闭csrf
                .csrf().disable()
        //添加自定义过滤器
        .addFilterAt(myJsonLoginFilter(), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
//    @Bean
//    public InMemoryUserDetailsManager userDetailsService() {
//        UserDetails user = User.withDefaultPasswordEncoder()
//                .username("aaa")
//                .password("111aaa")
//                .roles("USER")
//                .build();
//        return new InMemoryUserDetailsManager(user);
//    }

//    @Bean
//    public PasswordEncoder passwordEncoder() {
//        return new MyPasswordEncoder();
//    }


    @Bean
    JsonLoginFilter myJsonLoginFilter() throws Exception {
        JsonLoginFilter myJsonLoginFilter = new JsonLoginFilter();
        myJsonLoginFilter.setAuthenticationSuccessHandler(new LoginSuccessHandler());
        myJsonLoginFilter.setAuthenticationFailureHandler(new LoginFailureHandler());
        myJsonLoginFilter.setAuthenticationManager(authenticationManager());
        return myJsonLoginFilter;
    }



    @Bean
    AuthenticationManager authenticationManager(){
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        //设置用户信息处理器
        daoAuthenticationProvider.setUserDetailsService(userDetailService);
        //设置密码处理器
        daoAuthenticationProvider.setPasswordEncoder(new MyPasswordEncoder());
        ProviderManager pm = new ProviderManager(daoAuthenticationProvider);
        return pm;
    }

}




git地址:https://gitee.com/guan0207/puyu

但是登录成功后,还是未登录状态,SecurityContextHolder.getContext().getAuthentication().getPrincipal()取出来是anonymousUser是咋回事?

  • 写回答

6条回答 默认 最新

  • 「已注销」 2023-06-28 16:25
    关注

    可能的原因是在SecurityConfiguration类中配置的身份验证提供程序(DaoAuthenticationProvider)未正确地加载用户详细信息或密码处理器。
    确保以下内容:
    1.UserDetailServiceImpl类实现了UserDetailsService接口,并正确加载用户详细信息。
    2.MyPasswordEncoder类实现了PasswordEncoder接口,并正确处理密码。
    3.在authenticationManager()方法中,将用户信息处理器(userDetailService)和密码处理器(MyPasswordEncoder)正确配置给DaoAuthenticationProvider。

    调试和检查上述配置,确保用户详细信息和密码被正确加载和处理。如果问题仍然存在,那问题就出在UserDetailServiceImpl或MyPasswordEncoder的代码里了

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月4日
  • 修改了问题 6月28日
  • 创建了问题 6月28日