0%

spring-security结合jwt和umi(react前端框架)企业级框架之前后端分离最佳实战的小插曲-json模式登录

在这里插入图片描述

前言

众所周知,spring-security默认是form表单模式登录的,故我们只要在前端用表单提交即可,回顾我上次umi前端请求处理,代码如下

1
2
3
4
5
6
7
8
9
10
11
/**
* 成功登录获得token
* @param {*} params
*/
export async function fakeAccountLogin(params) {
return request('/login', {
method: 'POST',
data: params,
requestType: 'form' // 后端请求token需要表单的形式
});
}

很明显,request使用了requestType这个属性,决定了表单形式。所以能直接进入spring-security的默认方法了进行认证。

针对使用json模式

在这里我们只要稍微处理一下就可以

  • 处理SpringConfig

    原来:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
      @Override
    protected void configure(HttpSecurity http) throws Exception {
    http
    // 让跨域配置被使用
    .formLogin().successHandler(myAuthenticationSuccessHandler)
    .failureHandler(myAuthenticationFailHandler)
    .and()
    .cors()
    .and()
    .csrf().disable()
    // 添加异常处理
    .exceptionHandling()
    .authenticationEntryPoint(tokenExceptionHandler)
    .accessDeniedHandler(accessDeniedException)
    .and()
    //关闭session
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()

    // 拦截所有请求
    .authorizeRequests()
    .antMatchers(HttpMethod.POST,"/api/login").permitAll()
    .antMatchers("/api/**").authenticated();

    // 替换过滤器
    http.addFilterAt(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

    }

改变后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
http

.cors()
.and()
.csrf().disable()
// 添加异常处理
.exceptionHandling()
.authenticationEntryPoint(tokenExceptionHandler)
.accessDeniedHandler(accessDeniedException)
.and()
//关闭session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()

// 拦截所有请求
.authorizeRequests()
.antMatchers(HttpMethod.POST,"/api/login").permitAll()
.antMatchers("/api/**").authenticated();

// 替换过滤器
http.addFilterAt(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

在这里一对比很明显就看到,已经去掉了form的处理形式,包括成功和失败的处理器

1
2
3
4
5
6

@Bean(name = "myAuthenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}

还有在config里面增加了认证管理器的bean,这个是最重要的。

  • 增加loginController的处理方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* @Description LoginController
* @Author YiLong Wu
* @Date 2020/2/28 13:43
* @Version 1.0.0
*/
@RestController
@Slf4j
public class LoginController {

@Resource(name = "userDao")
private UserDao userDao;

@Resource(name = "myAuthenticationManager")
private AuthenticationManager myAuthenticationManager;


@PostMapping("/login")
public Response login(@RequestBody UserDto userDto) {
log.info("************{}",userDto);
User byUsername = userDao.findByUsername(userDto.getUsername());

if(byUsername == null || !MD5Util.string2MD5(userDto.getPassword()).equals(byUsername.getPassword())) {
return new Response(-1,"用户名或密码错误",null);
}

// 进行认证
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDto.getUsername(),userDto.getPassword());
Authentication authenticate = myAuthenticationManager.authenticate(usernamePasswordAuthenticationToken);

//从authentication中获取用户信息
JwtUser userDetail= (JwtUser)authenticate.getPrincipal();
// 生成token
String token = JwtUtil.generateToken(userDetail.getUsername());
return new Response(200, "登录成功",token);
}
}

在这里主要是自己处理了,账号密码的错误提示,用UsernamePasswordAuthenticationToken接受用户的个人信息,这在spring-security里也是这样操作的,然后调用认证管理器AuthenticationManager 进行认证即可,从而进入到UserDatailsService进行一系列的处理,如同表单提交一样的去自动处理,就像我上一章节画的流程图一样。

在这里插入图片描述

-------------本文结束感谢你的阅读---------