java使用token实现认证_Java,SpringBoot采用token方式实现登录认证

Token,令牌,访问资源的凭证,每次访问带上这个令牌,就可识别出用户身份。

JWT (JsonWebToken),是实现token技术的一种解决方案,由三部分组成: header(头)、payload(载体)、signature(签名)。

1、头:HS384 HS512 RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384

2、载体:

iss:Issuer,发行者sub:Subject,主题

aud:Audience,观众exp:Expiration time,过期时间

nbf:Not before

iat:Issued at,发行时间

jti:JWT ID

3、签名

代码案例:import io.jsonwebtoken.Claims;import io.jsonwebtoken.CompressionCodecs;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import javax.crypto.spec.SecretKeySpec;import java.security.Key;import java.util.Date;import java.util.HashMap;import java.util.Map;import java.util.UUID;

public class JJWTTokenApply {// 使用的Keypublic static Key KEY = new SecretKeySpec('密钥'.getBytes(), SignatureAlgorithm.HS512.getJcaName());/**

* @param expiration==>失效时间

* @return

*/public static String generateAccessToken(String subject, Map claimsMap, long expiration) {// 生成Tokenreturn Jwts.builder()

.setClaims(claimsMap)

.setSubject(subject)

.setId(UUID.randomUUID().toString())

.setIssuedAt(new Date())

.setExpiration(new Date(System.currentTimeMillis()   expiration * 1000))

.compressWith(CompressionCodecs.DEFLATE)

.signWith(SignatureAlgorithm.HS256, KEY)

.compact();

}/**

* @param token * @return */public static Map parseAccessToken(String token) {Map claimsMap = new HashMap(16);try {

Claims claims = Jwts.parser()

.setSigningKey(KEY)

.parseClaimsJws(token)

.getBody();// 失效时间claimsMap.put('expiration', claims.getExpiration());// 签发者claimsMap.put('created', claims.getIssuedAt());

claimsMap.put('subject', claims.getSubject());

claimsMap.put('user_id', claims.get('user_id'));

claimsMap.put('user_info', claims.get('user_info'));

claimsMap.put('user_roles', claims.get('user_roles'));

} catch (Exception e) {

e.printStackTrace();

}return claimsMap;

}

public static void main(String[] args) {// 主题String subject = 'zhangsan';// 加密数据Map claimsMap = new HashMap(16);

claimsMap.put('user_id', 123);

claimsMap.put('user_info', '用户信息');

claimsMap.put('user_roles', '用户角色');// 失效期1天String token = generateAccessToken(subject, claimsMap, 86400);

System.out.println('accessToken='   token);// 解析tokenMap parseMap = parseAccessToken(token);

System.out.println('主题='   parseMap.get('subject'));

System.out.println('user_id='   parseMap.get('user_id'));

System.out.println('user_info='   parseMap.get('user_info'));

System.out.println('user_roles='   parseMap.get('user_roles'));Date expirationDate = (Date) parseMap.get('expiration');

System.out.println('是否失效='   expirationDate.before(new Date()));

System.out.println('失效日期='   expirationDate);

System.out.println('失效时间='   (expirationDate.getTime() - System.currentTimeMillis()));

}

}

SpringBoot采用token方式实现认证

1、SpringSecurity的配置

public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {

CustomAuthenticationProvider customAuthenticationProvider = new CustomAuthenticationProvider(userDetailsService);

authenticationManagerBuilder.authenticationProvider(customAuthenticationProvider);

}@Overrideprotected void configure(HttpSecurity http) throws Exception {

http.cors().and().csrf().disable()

.authorizeRequests() // 请求授权// 配置路径放行.antMatchers('/**').permitAll()

.antMatchers(HttpMethod.GET, '/webSocket/**').permitAll()// swagger 文档.antMatchers('/swagger-ui.html').permitAll()

.antMatchers('/swagger-resources/**').permitAll()// druid.antMatchers('/druid/**').permitAll()// 放行OPTIONS请求.antMatchers(HttpMethod.OPTIONS, '/**').permitAll()// 其他都需要验证.anyRequest().authenticated()

.and()

.addFilter(new JWTAuthenticationFilter(authenticationManager(), userDetailsService))

.addFilter(new JWTAuthorizationFilter(authenticationManager()))// 不需要session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

}@BeanCorsConfigurationSource corsConfigurationSource() {final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

source.registerCorsConfiguration('/**', new CorsConfiguration().applyPermitDefaultValues());return source;

}

}

解析:部分代码没贴,实现的类重点包含:JWTAuthenticationFilter、JWTAuthorizationFilter、CustomAuthenticationProvider

2、登录认证的执行流程

215671957_1_20210218081054865

3、代码实现部分public class CustomAuthenticationProvider implements AuthenticationProvider {private UserDetailsService userService;public CustomAuthenticationProvider(UserDetailsService userService){this.userService = userService;

}@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {

String username = authentication.getName();

String password = authentication.getCredentials().toString();// 验证用户和密码返回}@Overridepublic boolean supports(Class> authentication) {return authentication.equals(UsernamePasswordAuthenticationToken.class);

}

}

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {private AuthenticationManager authenticationManager;private UserDetailsService userDetailsService;private JwtUtils jwtUtils;public JWTAuthenticationFilter(AuthenticationManager authenticationManager, UserDetailsService userDetailsService) {this.authenticationManager = authenticationManager;this.userDetailsService = userDetailsService;// 精确指定认证地址super.setFilterProcessesUrl('/api/authen/login');

}@Overridepublic Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

Authentication returnAuthentication = null;try {

AuthenUser loginUser = new ObjectMapper().readValue(request.getInputStream(), AuthenUser.class);

Authentication authenticationToken = new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword(), new ArrayList<>());

returnAuthentication = authenticationManager.authenticate(authenticationToken);return returnAuthentication;

} catch (IOException e) {

e.printStackTrace();

}return null;

}// 成功验证后调用该方法@Overrideprotected void successfulAuthentication(HttpServletRequest request,

HttpServletResponse response,

FilterChain chain,

Authentication authen) throws IOException, ServletException {

String username = (String) authen.getPrincipal();

UserDetails userDetail = (UserDetails) userDetailsService.loadUserByUsername(username);

String token = jwtUtils.generateAccessToken(userDetail);

HashMap resultData = Maps.newHashMap();

resultData.put('token', token);

resultData.put('userInfo', userDetail);

resultData.put('headerName', JwtUtils.TOKEN_HEADER);

resultData.put('prefix', JwtUtils.TOKEN_PREFIX);

resultData.put('tokenExpiration', jwtUtils.getExpireTime(jwtUtils.getAccess_token_expiration()));

String json = JSONObject.toJSONString(ServerResponse.createBySuccess(resultData));

response.setCharacterEncoding('UTF-8');

response.setContentType('application/json; charset=utf-8');

response.getWriter().write(json);

}@Overrideprotected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {if (failed instanceof BadCredentialsException) {

response.setCharacterEncoding('utf-8');

response.getWriter().write(JSONUtil.toJsonStr(ServerResponse.createDefaultErrorMessage(failed.getMessage())));

} else if (failed instanceof UsernameNotFoundException) {

response.setCharacterEncoding('utf-8');

response.getWriter().write(JSONUtil.toJsonStr(ServerResponse.createDefaultErrorMessage(failed.getMessage())));

} else {

response.getWriter().write('authentication failed, reason: ' failed.getMessage());

}

}

}

认证登录成功后,返回JSON串,包含token。

3、再次请求

215671957_2_20210218081055474

4、代码处理部分public class JWTAuthorizationFilter extends BasicAuthenticationFilter {public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {super(authenticationManager);

}@Overrideprotected void doFilterInternal(HttpServletRequest request,

HttpServletResponse response,

FilterChain chain) throws IOException, ServletException {

String tokenHeader = request.getHeader('Authorization');// HTTP头中的Authorization信息if (tokenHeader == null || !tokenHeader.startsWith('Bearer ')) {

chain.doFilter(request, response);return;

}try {             // 解析token,并且设置认证信息SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));

} catch (TokenIsExpiredException e) {

response.setCharacterEncoding('UTF-8');

response.setContentType('application/json; charset=utf-8');

response.setStatus(HttpServletResponse.SC_FORBIDDEN);

String reason = '错误:'   e.getMessage();

response.getWriter().write(new ObjectMapper().writeValueAsString(reason));

response.getWriter().flush();return;

}super.doFilterInternal(request, response, chain);


版权声明:本文为weixin_31869579原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。