Spring Boot使用JWT实现系统登录验证
简介
什么是JWT(Json Web Token)
jwt是为了在网络应用环境间传递声明而执行的一种基于json的开放标准。该token被设计紧凑且安全的,特别适用于SSO场景。
jwt的声明一般被用来在身份提供者和服务提供者之间传递被认证的用户身份信息。
JWT长什么样
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MDAyIiwiZXhwIjoxNTEwOTcwMjU4fQ._FOqy5l44hODu3DjXh762LNUTLNQH15fdCUerdseDpmSKgkVSCjOyxQNTBKDSh3N-c83_pdEw5t6BdorgRU_kw
JWT的构成
JWT通常由三部分组成,头信息(header)、消息体(body)、签名(signature)
头信息指定了JWT使用的签名算法
header={alg=HS512}
消息体包含了JWT的意图,exp为令牌过期时间
body={sub=testUsername, exp=1510886546}
签名通过私钥生成
signature=kwq8a_B6WMqHOrEi-gFR5rRPmPL7qoShZJn0VFfXpXc1Yfw6BfVrliAP9C4UnXlqD3wRXO3mw_DDIdglN5lH9Q
使用springboot集成jwt
引用依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency> <dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
构建普通rest接口
@RestController
@RequestMapping("/employee")
public class EmployeeController { @GetMapping("/greeting")
public String greeting() {
return "Hello,World!";
}
}
JwtLoginFilter
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter { private AuthenticationManager authenticationManager; public JwtLoginFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
} @Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
Employee employee = new Employee();
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
employee.getUsername(),
employee.getPassword(),
new ArrayList<>()
)
);
} @Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
String token = Jwts.builder()
.setSubject(((User) authResult.getPrincipal()).getUsername())
.setExpiration(new Date(System.currentTimeMillis() + 30 * 60 * 1000))
.signWith(SignatureAlgorithm.HS512, "JWTSecret")
.compact(); response.addHeader("Authorization", JwtUtils.getTokenHeader(token));
}}
JwtAuthenticationFilter
public class JwtAuthenticationFilter extends BasicAuthenticationFilter { public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
} @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String header = request.getHeader("Authorization"); if (header == null || !header.startsWith(JwtUtils.getAuthorizationHeaderPrefix())) {
chain.doFilter(request, response);
return;
} UsernamePasswordAuthenticationToken authenticationToken = getUsernamePasswordAuthenticationToken(header); SecurityContextHolder.getContext().setAuthentication(authenticationToken);
chain.doFilter(request, response);
} private UsernamePasswordAuthenticationToken getUsernamePasswordAuthenticationToken(String token) {
String user = Jwts.parser()
.setSigningKey("PrivateSecret")
.parseClaimsJws(token.replace(JwtUtils.getAuthorizationHeaderPrefix(), ""))
.getBody()
.getSubject(); if (null != user) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
} return null;
}
}
SecurityConfiguration
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.anyRequest().authenticated()
.and()
.addFilter(new JwtLoginFilter(authenticationManager()))
.addFilter(new JwtAuthenticationFilter(authenticationManager()));
} }
使用postman测试
首先我们先测试/employee/greeting 响应如下:
{
"timestamp": 1510887634904,
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/employee/greeting"
}
很明显,状态码为403,此刻我们如果先登录拿到token后再测试呢,测试如下
登录成功后,我们可以看到headers中已经带有jwt
authorization →Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0VXNlcm5hbWUiLCJleHAiOjE1MTA4ODkxMDd9.FtdEM0p84ff5CzDcoiQhtm1MF_NfDH2Ij1jspxlTQhuCISIzYdoU40OsFoxam9F1EXeVw2GZdQmArVwMk6HO1A
由于postman在一般情况下不支持自定义header 这个时候我们需要下载一个插件开启interceptor 开启后将authorization 放入header继续测试:
这时我们发现已经成功返回hello,world!
最后附上代码GitHub地址:源码下载
本文转载自
原文作者:胡运凡
最新文章
- PHP语法(二):数据类型、运算符和函数
- 谢欣伦 - OpenDev原创例程 - 时间同步Time Sync
- 如何在一个页面后面随机跳转到多个链接地址Math.floor()和Math.random()
- 【NodeJS线程】Boss和他的职员们
- 根据键盘调整textField(多个)位置使其不会被键盘挡住
- Lanterns
- 【转载】解决 Subversion 的 “svn: Can&#39;t convert string from &#39;UTF-8&#39; to native encoding” 错误
- oracle 导入数据
- 8051学习笔记——AD
- java-读取属性文件
- CentOS服务端口开放
- HDU5842
- java.lang.IllegalArgumentException: Document base D:\Project\workspace\space\.metadata\.plugins\org.eclipse.wst.server.core\tmp7\wtpwebapps\Blog
- 20162328蔡文琛week05
- 简介---linux内核态和用户态
- windows驱动开发前导知识
- Centos 7.3下 Linux For SQL Server安装及配置介绍
- 一次docker中的nginx进程响应慢问题定位记录
- 使用crf++
- springboot +element-axios跨域请求