基于Spring Security的登录验证功能

后端:

1.引入maven依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session-core</artifactId>
</dependency>

2.配置代码

package com.breeze.bms.config;

import com.breeze.bms.bean.MessageCode;
import com.breeze.bms.bean.Result;
import com.breeze.bms.bean.vo.LoginRes;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.cors.CorsUtils;

import javax.annotation.Resource;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author breeze
 * @since 2021/9/17 9:55
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    ObjectMapper objectMapper;
    @Qualifier("customUserDetailService")
    @Autowired
    UserDetailsService userDetailsService;


    @Override
    public void configure(WebSecurity web) throws Exception {
        //配置免登陆接口
        web.ignoring().antMatchers("/doc.html", "/webjars/**", "/swagger-resources/**", "/v2/api-docs", "/anonymous/**","/stomp/websocketJS/**");
        super.configure(web);
    }

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

        http.sessionManagement().invalidSessionStrategy((request, response) -> {
            response.setContentType("application/json;charset=utf-8");
            PrintWriter out = response.getWriter();
            out.write(objectMapper.writeValueAsString(Result.failResult(MessageCode.NO_LOGIN)));
            out.flush();
            out.close();
        }).and().cors()
                .and().csrf().disable()
                .authenticationProvider(authenticationProvider())
                .httpBasic()
                //未登录时,进行json格式的提示
                .authenticationEntryPoint((request, response, authException) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(objectMapper.writeValueAsString(Result.failResult(MessageCode.NO_LOGIN)));
                    out.flush();
                    out.close();
                })
                .and()
                .authorizeRequests()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .anyRequest().authenticated() //必须授权才能范围

                .and()
                .formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login").loginProcessingUrl("/login")
                .permitAll()
                //登录失败,返回json
                .failureHandler((request, response, ex) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    Result result = Result.failResult("401", "登录失败");
                    if (ex instanceof UsernameNotFoundException) {
                        result.setMessage("未找到相关账户");
                    } else if (ex instanceof BadCredentialsException) {
                        result.setMessage("账户密码错误");
                    } else if (ex instanceof DisabledException) {
                        result.setMessage("账户被禁用");
                    }
                    out.write(objectMapper.writeValueAsString(result));
                    out.flush();
                    out.close();
                })
                //登录成功,返回json
                .successHandler((request, response, authentication) -> {
                    Result result = Result.successResult();
                    result.setData(LoginRes.builder().token(request.getSession().getId()).authentication(authentication).build());
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(objectMapper.writeValueAsString(result));
                    out.flush();
                    out.close();
                })
                .and()
                .exceptionHandling()
                //没有权限,返回json
                .accessDeniedHandler((request, response, ex) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    Result result = Result.failResult(MessageCode.NO_LOGIN, "权限不足");
                    out.write(objectMapper.writeValueAsString(result));
                    out.flush();
                    out.close();
                })
                .and()
                .logout()
                //退出成功,返回json
                .logoutSuccessHandler((request, response, authentication) -> {
                    Map<String, Object> map = new HashMap<String, Object>();
                    Result result = Result.successResult();
                    result.setData(authentication);
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(objectMapper.writeValueAsString(result));
                    out.flush();
                    out.close();
                })
                .permitAll();
    }


    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        //对默认的UserDetailsService进行覆盖
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }


    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

3.获取用户的UserDetail实现

package com.breeze.bms.security;

import com.breeze.bms.mybatis.domain.SysUser;
import com.breeze.bms.service.SysUserService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author breeze
 * @since 2021/9/17 11:03
 */
@Service("customUserDetailService")
public class UserDetailsServiceImpl implements UserDetailsService {
    @Resource
    SysUserService sysUserService; //自己的用户管理服务
    @Override
    public UserDetails loadUserByUsername(String loginName) throws UsernameNotFoundException {
        SysUser sysUser = sysUserService.queryByLoginName(loginName);

        return sysUser;
    }
}

4.设置SpringSession头,如果不想自定义默认就行

package com.breeze.bms.config;

import org.springframework.context.annotation.Bean;
import org.springframework.session.MapSession;
import org.springframework.session.MapSessionRepository;
import org.springframework.session.SessionRepository;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
import org.springframework.session.web.http.HeaderHttpSessionIdResolver;
import org.springframework.session.web.http.HttpSessionIdResolver;

import java.util.concurrent.ConcurrentHashMap;

@EnableSpringHttpSession
public class SpringSessionConfig {
    @Bean
    public SessionRepository<MapSession> sessionRepository() {
        return new MapSessionRepository(new ConcurrentHashMap<>());
    }
    @Bean
    public HttpSessionIdResolver sessionIdResolver() {
        return new HeaderHttpSessionIdResolver("X-Token");
    }
}

前端:

request({
    url: '/login',
    method: 'post',
    data,
    transformRequest: [
      function(data) {
        let ret = ''
        for (const it in data) {
          ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
        }
        ret = ret.substring(0, ret.lastIndexOf('&'))
        return ret
      }
    ],
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  })

其他访问授权接口的时候把登录返回的token放到请求头X-Token(此处为后端4.Spring Session里自定义的头)里就行,如下所示

service.interceptors.request.use(
  config => {
    // do something before request is sent

    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['X-Token'] = JSON.parse(getToken()).token
    }
    return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eclipsewangwfUN

棋盘内,车无轮马无缰,叫声将军

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值