整合JWT
我们前几个小节,实现的是非前后端分离情况下的认证与授权的处理,目前大部分项目,都是使用前后端分离的模式。那么前后端分离的情况下,我们如何使用SpringSecurity来解决权限问题呢?最常见的方案就是SpringSecurity+JWT
认证流程
-
同步认证:登录之后会自动被框架的过滤器拦截,然后或许用户信息进行认证
-
前后端分离认证:自定义登录接口,主动调用框架进行认证,使用的是框架提供的认证管理器
认证实现
环境准备
-
为了快速搞定环境,我们新创建一个项目springsecurity-jwt,注意把上一个demo工程的代码和pom都拷贝过来
-
从zzyl-common模块中工具类JwtUtil拷贝到当前项目中 ,用于生成和验证 JWT令牌
pom文件依赖
java
<!--JWT-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.0.M3</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
定义认证管理器
自定义授权管理属于全局,我们需要让它被spring容器进行管理,所以我们可以把它配置在SecurityConfig配置类中
在SecurityConfig添加创建认证管理器的代码,如下:
java
package com.itheima.project.web;
import com.itheima.project.entity.LoginDto;
import com.itheima.project.entity.UserAuth;
import com.itheima.project.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @author sjqn
*/
@RestController
@RequestMapping("/security")
public class LoginController {
@Autowired
private AuthenticationManager authenticationManager;
@PostMapping("/login")
public String login(@RequestBody LoginDto loginDto){
//包装用户的密码
UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(loginDto.getUsername(),loginDto.getPassword());
//需要一个认证管理器,来进行调用
Authentication authenticate = authenticationManager.authenticate(upat);
//判断认证是否成功
if(authenticate.isAuthenticated()){
//获取用户
UserAuth userAuth = (UserAuth) authenticate.getPrincipal();
//认证成功
//生成jwt,返回
Map<String,Object> map = new HashMap<>();
map.put("user",userAuth);
String token = JwtUtil.createJWT("itcast", 360000, map);
return token;
}
return "";
}
}
登录功能实现
有了认证管理器之后,我们就可以在自己的登录接口中来使用认证管理器完成认证的操作
下面是自定义接口完成认证
java
package com.itheima.project.web;
import com.itheima.project.entity.LoginDto;
import com.itheima.project.entity.UserAuth;
import com.itheima.project.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @author sjqn
*/
@RestController
@RequestMapping("/security")
public class LoginController {
@Autowired
private AuthenticationManager authenticationManager;
@PostMapping("/login")
public String login(@RequestBody LoginDto loginDto){
//包装用户的密码
UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(loginDto.getUsername(),loginDto.getPassword());
//需要一个认证管理器,来进行调用
Authentication authenticate = authenticationManager.authenticate(upat);
//判断认证是否成功
if(authenticate.isAuthenticated()){
//获取用户
UserAuth userAuth = (UserAuth) authenticate.getPrincipal();
//认证成功
//生成jwt,返回
Map<String,Object> map = new HashMap<>();
map.put("user",userAuth);
String token = JwtUtil.createJWT("itcast", 360000, map);
return token;
}
return "";
}
}
LoginDto
java
package com.itheima.project.entity;
import lombok.Data;
@Data
public class LoginDto {
private String username;
private String password;
}
修改自定义配置,由于目前是接口开发,无需在使用自定义登录页面,只需要放行登录接口就行了
java
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//构建自定义配置
http.authorizeHttpRequests().antMatchers("/security/login").permitAll();
http.csrf().disable();
return http.build();
}
测试
使用ApiFox测试
- 输入正确的用户名和密码,则会返回jwt生成的token,也就说明认证成功了