我来为您讲解“Java实现基于token认证的方法示例”的完整攻略。
什么是token认证
Token认证是现在比较流行的Web应用程序认证方法之一。它能解决基于session认证的一些问题,比如跨站点请求伪造(CSRF)和分布式系统中的会话共享的问题。用户只需要通过用户名和密码一次验证,在服务器成功认证后,服务器会返回一个token给客户端。客户端在后续的访问请求中带上这个token来进行身份验证,避免了使用 cookie 造成的一些基于 session 认证的安全问题。
实现基于token认证的方法
要实现基于token认证的方法具体分为以下步骤:
- 用户登录时,客户端向服务器发送用户名和密码。
- 服务器验证用户名和密码是否正确,如果正确则在服务器端生成一个token,并保存该 token 到数据库中。同时返回给客户端该token作为登录凭证。
- 客户端将这个 token 存储在本地存储器中,例如localStorage。
- 在每次向服务器发送请求时,客户端将token添加到请求的头部中,例如Authorization头部。
- 服务器通过获取请求头部中的 Authorization 字段获取该请求的token,然后从数据库中查询该 token 是否存在。如果存在,则说明该请求的用户已经通过了身份认证,服务器为请求提供相应的服务。
下面给出一个Java实现基于token认证的示例,帮助大家更好的理解token认证的流程。
示例一
这个示例使用Spring框架实现基于token认证的方法。
首先,我们需要在Spring Security中配置Token-Based Authentication:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
pivate JwtTokenUtil jwtTokenUtil;
@Bean
public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
return new JwtAuthenticationTokenFilter();
}
@Override
protected voird configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated();
// 添加一个过滤器以验证token
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
// 禁用缓存
httpSecurity.headers().cacheControl();
}
@Override
public void configure(WebSecurity webSecurity) throws Exception {
// 允许 Swagger2 访问
webSecurity.ignoring().antMatchers("/v2/api-docs", "/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/images/**");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
在上述代码中,我们从用户获取其username和password来认证,如果成功,将生成并返回一个JWT token。此时,token已经保存在客户端中,可以在以后的请求中使用。
接下来,我们需要实现一个类来提供token的生成和验证功能。下面是一个示例:
@Service
public class JwtTokenService {
@Value("${jwt.secret}")
private String secret;
// 定义过期时间为1小时
private static final long EXPIRATION_TIME = 60 * 60 * 1000;
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put("sub", userDetails.getUsername());
claims.put("iat", new Date(System.currentTimeMillis()));
return Jwts.builder()
.setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
public String getUsernameFromToken(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject();
}
private Date getExpirationDateFromToken(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getExpiration();
}
private boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
}
在上面的代码中,我们定义了如下方法:
- generateToken:生成token;
- validateToken:验证token是否有效;
- getUsernameFromToken:获取token中的用户名;
- getExpirationDateFromToken:获取token的过期时间;
- isTokenExpired:判断token是否过期。
我们还可以验证前端传过来的 token 是否合法,下面是一个示例:
@Service
public class JwtUserDetailsService implements UserDetailsService {
@Autowired
private JwtTokenService jwtTokenService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 假设这里是从数据库中查询用户信息
return new User(username, "", new ArrayList<>());
}
public boolean validateToken(String token) {
String username = jwtTokenService.getUsernameFromToken(token);
UserDetails userDetails = this.loadUserByUsername(username);
return jwtTokenService.validateToken(token, userDetails);
}
}
在上述代码中,当从前端接收到一个token时,在这个方法中调用jwtTokenService的validateToken方法验证该token是否合法。
示例二
下面是一个更简单的示例,使用JAX-RS框架和Jersey实现基于token认证的方法。在 Jersey 中使用 HTTP 请求处理函数(@POST, @GET, @PUT, @DELETE) 和 Resouce 模块(@Path、@Produces、@Consumes)定义一个 API。此示例使用的是 JJWT(JSON Web Token for Java) 以及基本的 web servlet,其余的代码都是 java。
@Path("/your/resource")
public class YourResource {
@POST
@Path("/login")
@Consumes(MediaType.APPLICATION_JSON)
public Response login(User user) {
// ...
String jwt = createJWT(user);
return Response.ok().entity(jwt).build();
}
@GET
@Path("/secured")
@Produces(MediaType.APPLICATION_JSON)
public Response secureEndpoint(@HeaderParam("Authorization") String authHeader) throws JsonProcessingException {
// 验证 token 是否正确
JwtToken jwtToken = JwtTokenService.verifyToken(authHeader);
if (jwtToken != null && jwtToken.getPayload().get("sub") != null) {
// 用户重载并返回受保护的数据
User user = retrieveUserFromDatabase(jwtToken.getPayload().get("sub").toString());
return Response.ok().entity(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user)).build();
}
return Response.status(Response.Status.UNAUTHORIZED).build();
}
@SuppressWarnings("deprecation")
private String createJWT(User user) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, 7);
JwtBuilder builder = Jwts.builder()
.setPayload(new Gson().toJson(user))
.setExpiration(calendar.getTime())
.signWith(SignatureAlgorithm.HS512, "mySecretKey");
return builder.compact();
}
private User retrieveUserFromDatabase(String username) {
// ...
return new User();
}
}
在上述代码中,我们定义了一个包含两个方法的类YourResource,其中:
- login() 方法是一个带有@POST注解的方法,用于从客户端获取用户凭证。在这个方法里,我们生成JWT并返回给客户端,客户端将此token保存在本地存储器中。
- secureEndpoint() 方法是一个带有@GET注解的方法,在前端发来的请求中验证此请求的 token 是否有效,如果有效,返回受保护的文本数据。在这个方法中,我们调用
JwtTokenService
的verifyToken
方法来验证token是否有效。
至此,我们就学习到了Java实现基于token认证的方法。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现基于token认证的方法示例 - Python技术站