使用JWT實現用戶認證
本文用一個簡單的例子來使用Json Web Token (JWT)實現用戶登陸以及認證的功能Github源碼
採用了RESTful的設計方式,採用Spring Boot + Ignite + JWT的技術,使用Postman對API進行測試
API接口如下:
用戶註冊:/register
使用POST方式請求
用戶登陸:/login
使用POST方式請求
用戶認證測試接口:/secure/users/user
使用POST方式請求
其中用戶註冊與登陸的請求JSON格式如下:
{
"username":"XXX",
"password":"XXX"
}
JWT概念解析
關於JWT相關的概念網上有很多的文章可以參考,這裏附上幾個感覺講的很好的文章12
JWT與Spring Boot的整合
1.配置JWT過濾器信息,將請求頭部中authorization
的信息提取出來,並通過簽名的Key進行比對,判斷是否是合法的JWT token
public class JwtFilter extends GenericFilterBean {
public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
final String authHeader = request.getHeader("authorization");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
chain.doFilter(req, res);
} else {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw new ServletException("Missing or invalid Authorization header");
}
final String token = authHeader.substring(7);
try {
final Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
} catch (final SignatureException e) {
throw new ServletException("Invalid token");
}
chain.doFilter(req, res);
}
}
}
2.在Spring Boot主方法中添加@Bean
配置需要認證的接口信息,並啓動JwtFIlter
@SpringBootApplication
@EnableIgniteRepositories
public class UsersApplication {
@Bean
public FilterRegistrationBean jwtFilter() {
final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new JwtFilter());
registrationBean.addUrlPatterns("/secure/*");
return registrationBean;
}
public static void main(String[] args) {
SpringApplication.run(UsersApplication.class, args);
}
}
3.在用戶進行登陸的過程中,將用戶的用戶名作爲JWT的一個屬性進行編碼生成JWT token
@RestController
public class PersonController {
@Autowired
private PersonService personService;
/**
* Check user`s login info, then create a jwt token returned to front end
* @param reqPerson
* @return jwt token
* @throws ServletException
*/
@PostMapping
public String login(@RequestBody() ReqPerson reqPerson) throws ServletException {
// Check if username and password is null
if (reqPerson.getUsername() == "" || reqPerson.getUsername() == null
|| reqPerson.getPassword() == "" || reqPerson.getPassword() == null)
throw new ServletException("Please fill in username and password");
// Check if the username is used
if(personService.findPersonByUsername(reqPerson.getUsername()) == null
|| !reqPerson.getPassword().equals(personService.findPersonByUsername(reqPerson.getUsername()).getPassword())){
throw new ServletException("Please fill in username and password");
}
// Create Twt token
String jwtToken = Jwts.builder().setSubject(reqPerson.getUsername()).claim("roles", "member").setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS256, "secretkey").compact();
return jwtToken;
}
}
測試結果
- 註冊用戶,添加用戶到數據庫
- 在進行用戶的登陸,登陸成功後獲得Web Service返回的Jwt token信息
- 在不使用或使用錯誤的Jwt token信息訪問測試接口
/secure/users/user
時認證失敗
- 在使用正確的token信息訪問測試接口時認證成功