springSecurity 登录及验证登录实现

整体流程:

1、核心类websecurityAdapter(需要注意的我都注释了

//注意这个注解一定要加
@EnableWebSecurity
public class WebSecuirityAdapter extends WebSecurityConfigurerAdapter {

    @Autowired
    private LoginSuccessHandler successHandler;
    @Autowired
    private LoginFailHandler failHandler;
    @Autowired
    private MyUserDetailsService myUserDetailsService;


    //将用户信息加载到security
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity
                .authorizeRequests();
        registry.and()
                // 表单登录方式
                .formLogin()
                // 登录请求url
                .loginProcessingUrl("/user/login")
//                .loginPage("https://www.baidu.com")
                .permitAll()
                .successHandler(successHandler)
                .failureHandler(failHandler)
                .and()
                .authorizeRequests()
                // 任何请求
                .anyRequest()
                // 需要身份认证
                .authenticated()
                .and()
                // 注意这个要关闭,否则可能因为这里验证导致无法使用自定义token访问数据,关闭跨站请求防护
                .csrf().disable()
                .addFilter(new MyAuthenticationFilter(authenticationManager()))
                // 前后端分离 不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        ;
    }
}

2、SecurityUser,可以继承用户自定义user,相当于给自定义user进行了封装,供框架使用

@Data
public class SecurityUser extends User implements UserDetails {

    //此用户是否禁用,禁用0,可用1
    private String status;
    private Boolean enabled;
    private Boolean credentialsNonExpired;
    private Boolean accountNonExpired;
    private Boolean accountNonLocked;
    private Collection<? extends GrantedAuthority> authorities;

    public SecurityUser(){};

    public SecurityUser(User user){
        this.setId(user.getId());
        this.setNickname(user.getNickname());
        this.setUsername(user.getUsername());
        this.setPassword(user.getPassword());
        this.setUsertype(user.getUsertype());
        this.setStatus(user.getStatus());
        this.setValidtime(user.getValidtime());
        this.setTelephone(user.getTelephone());
        this.setEmail(user.getEmail());
        this.setUpdateby(user.getUpdateby());
        this.setUpdatetime(user.getUpdatetime());
        this.setRoles(user.getRoles());
        status = user.getStatus();
    }

    //将role加载到Collection中,后续在加载到springsecurity
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {

        return null;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    //此用户是否可用,可用于禁用或启用用户,框架帮我们对禁用用户进行拦截
    @Override
    public boolean isEnabled() {
        return status.equals("1");
    }
}

3、MyUserDetailsService

@Component
public class MyUserDetailsService implements UserDetailsService {
    @Autowired
    IUserService iUserService;

    //用户前台表单输入的用户名会传到这里,然后用这个名去数据库查询是否有这个用户,有的话加载到security内存中,然后再验证前台传来的密码是不是正确的
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = null;
        if(StringUtils.isNotBlank(username)){
            user = iUserService.findByName(username);
        }else {
            throw new SystemException("请填写用户名");
        }
        if(null!=user){
            return new SecurityUser(user);
        }else {
            throw new SystemException("该用户不存在");
        }

    }
}

4、LoginSuccessHandler  (里面是登录成功进行的处理,可以存储自定义token,进行进一步用户验证等)

@Component
public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Value("${token.tokenExpireTime}")
    private Integer tokenExpireTime;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private GlobalValueConfig VALUECONFIG;
    @Autowired
    private IUserService iUserService;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth) throws ServletException, IOException {
        SecurityUser user = (SecurityUser) auth.getPrincipal();
        String username = user.getUsername();
     

        //登录成功,先检查之前是否已经有该用户的登录信息,有的话清掉
        String oldToken = (String)redisUtil.hget(VALUECONFIG.UserToken, username);
        if(null!=oldToken){
            redisUtil.hdel(VALUECONFIG.UserToken,username);
            redisUtil.hdel(VALUECONFIG.TokenInfo,oldToken);
        }

        // 将token存储到redis
        String token = null;
        token = UUID.randomUUID().toString().replace("-","");
        boolean set1 = redisUtil.hset(VALUECONFIG.TokenInfo,token, user, tokenExpireTime);
        boolean set2 = redisUtil.hset(VALUECONFIG.UserToken,username, token, tokenExpireTime);

        //将token返回给前端
        ResponseUtil.out(response,ResponseUtil.resultMap(true,200,token));
    }
}

5、LoginFailHandler(exception有很多种类型,可以判断出用户是因为什么登录失败的,我这里没有写那么详细,如果有需要可以细分)

@Component
public class LoginFailHandler extends SimpleUrlAuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        System.out.println(exception);
        ResponseUtil.out(response,ResponseUtil.resultMap(false,500,"登录失败"));
    }
}

6、MyAuthenticationFilter (其他请求的合法校验)

/**
 * @Author: WXM
 * @Description:
 * @Date: create in 2021/3/10 10:34
 */

public class MyAuthenticationFilter extends BasicAuthenticationFilter {

    private RedisUtil redisUtil = GetBeanUtil.getBean(RedisUtil.class);
    private GlobalValueConfig VALUECONFIG = GetBeanUtil.getBean(GlobalValueConfig.class);

    public MyAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    public MyAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
        super(authenticationManager, authenticationEntryPoint);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String wxmToken = request.getHeader(VALUECONFIG.TokenName);
        //如果token为空,则需要让用户登录
        if(StringUtils.isBlank(wxmToken)){
            chain.doFilter(request,response);
            return;
        }

        User user = (User)redisUtil.hget(VALUECONFIG.TokenInfo,wxmToken);
        if(null!=user){
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user,null,new ArrayList<>());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            chain.doFilter(request,response);
        }else {
            ResponseUtil.out(response,ResponseUtil.resultMap(false,401,"登录信息过期,请重新登录"));
        }


    }


}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security 提供了多种方式来验证登录,下面介绍其中的一种常用方式。 1. 配置 Spring SecuritySpring Security 的配置文件中,需要配置登录页面、登录请求处理的 URL、登录成功和失败的处理器等。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyUserDetailsService userDetailsService; @Autowired private RestAuthenticationEntryPoint restAuthenticationEntryPoint; @Autowired private MySavedRequestAwareAuthenticationSuccessHandler mySavedRequestAwareAuthenticationSuccessHandler; @Autowired private MySimpleUrlAuthenticationFailureHandler mySimpleUrlAuthenticationFailureHandler; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .exceptionHandling() .authenticationEntryPoint(restAuthenticationEntryPoint) .and() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .antMatchers("/api/user/login").permitAll() .anyRequest().authenticated() .and() .formLogin() .successHandler(mySavedRequestAwareAuthenticationSuccessHandler) .failureHandler(mySimpleUrlAuthenticationFailureHandler) .and() .logout() .logoutUrl("/api/user/logout") .logoutSuccessHandler(new MyLogoutSuccessHandler()); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder()); } } ``` 2. 自定义 UserDetailsService UserDetailsService 是一个接口,用于根据用户名获取用户信息,可以自定义实现该接口,以便获取自己的用户信息。 ```java @Service public class MyUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 从数据库中获取用户信息 User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found with username: " + username); } // 将用户信息转换为 UserDetails 对象 List<GrantedAuthority> authorities = new ArrayList<>(); for (Role role : user.getRoles()) { authorities.add(new SimpleGrantedAuthority(role.getName())); } return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities); } } ``` 3. 自定义登录成功或失败的处理器 登录成功或失败后,可以根据实际需求进行相应的处理,比如跳转到某个页面或者返回 JSON 数据。 ```java @Component public class MySavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException { // 登录成功后,可以进行相应的处理,比如跳转到某个页面或者返回 JSON 数据 response.setStatus(HttpServletResponse.SC_OK); } } @Component public class MySimpleUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { // 登录失败后,可以进行相应的处理,比如跳转到某个页面或者返回 JSON 数据 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } } ``` 4. 发送登录请求 在发送登录请求时,需要携带用户名和密码等参数,并将请求发送到登录处理的 URL 上。 ```javascript $.ajax({ url: '/api/user/login', type: 'POST', contentType: 'application/json', data: JSON.stringify({ username: 'admin', password: '123456' }), success: function(data) { // 登录成功后,可以进行相应的处理 }, error: function(xhr, status, error) { // 登录失败后,可以进行相应的处理 } }); ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值