首先需要创建2个过滤器. JwtLoginFilter 和 JwtAuthenticationFilter .
JwtLoginFilter 用来处理用户登录请求.
JwtAuthenticationFilter 用来处理JwtToken的验证解析.
/**
* @author: 阮胜
* @date: 2018/7/10 8:42
*/
public class JwtLoginFilter extends AbstractAuthenticationProcessingFilter {
private static final String POST = "POST";
private AuthenticationSuccessHandler successHandler = new JwtLoginSucessHandler();
private AuthenticationFailureHandler failureHandler = new JwtLoginFailureHandler();
public JwtLoginFilter(AuthenticationManager authenticationManager) {
super(new AntPathRequestMatcher("/user/login", "POST"));
setAuthenticationManager(authenticationManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
if (!request.getMethod().equals(POST)) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
String username = request.getParameter("username");
String password = request.getParameter("password");
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
PrintWriter writer = response.getWriter();
writer.write("用户名或者密码为空");
writer.close();
return null;
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
username, password);
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
return this.getAuthenticationManager().authenticate(authRequest);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
JwtToken jwtToken = new JwtToken(authResult.getName(), authResult.getAuthorities().iterator().next().toString(), jwtTokenUtil.generateExpirationDate());
String jwtTokenStr = jwtTokenUtil.generateToken(jwtToken);
response.addHeader("Authorization", jwtTokenStr);
successHandler.onAuthenticationSuccess(request, response, authResult);
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
failureHandler.onAuthenticationFailure(request, response, failed);
}
public void setSuccessHandler(AuthenticationSuccessHandler successHandler) {
this.successHandler = successHandler;
}
public void setFailureHandler(AuthenticationFailureHandler failureHandler) {
this.failureHandler = failureHandler;
}
}
/**
* @author: 阮胜
* @date: 2018/7/10 10:44
*/
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String jwtTokenStr = request.getHeader("Authorization");
if (!StringUtils.isEmpty(jwtTokenStr)) {
try {
if (!jwtTokenUtil.validateToken(jwtTokenStr)) {
throw new InvalidJwtTokenException();
}
JwtToken jwtToken = jwtTokenUtil.parseJwtToken(jwtTokenStr);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(jwtToken.getUsername(), null
, AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_".concat(jwtToken.getRole())));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
} catch (Exception e) {
sendError(response, "无效的Token");
return;
}
}
chain.doFilter(request, response);
}
private void sendError(HttpServletResponse response, String msg) throws IOException {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setContentType("text/plain;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(msg);
writer.close();
}
}
配置类:
/**
* @author: 阮胜
* @date: 2018/7/10 8:33
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final AccessDeniedHandler accessDeniedHandler;
private final AuthenticationEntryPoint authenticationEntryPoint;
private final UserDetailServiceImpl userDetailsService;
public SecurityConfig(AccessDeniedHandler accessDeniedHandler, AuthenticationEntryPoint authenticationEntryPoint, UserDetailServiceImpl userDetailsService) {
this.accessDeniedHandler = accessDeniedHandler;
this.authenticationEntryPoint = authenticationEntryPoint;
this.userDetailsService = userDetailsService;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new DefaultEncoder();
}
@Bean
public JwtLoginFilter jwtLoginFilter() throws Exception {
JwtLoginFilter jwtLoginFilter = new JwtLoginFilter(authenticationManager());
jwtLoginFilter.setAuthenticationSuccessHandler((request, response, authentication) -> {
System.out.println("success");
});
jwtLoginFilter.setAuthenticationFailureHandler((request, response, exception) -> {
System.out.println("false");
});
return jwtLoginFilter;
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
return new JwtAuthenticationFilter(authenticationManager());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin", "/admin/info").hasRole("ADMIN")
.anyRequest().permitAll()
.and().userDetailsService(userDetailsService)
//如果已经登录,但没有访问资源的权限,则调用该Handler
.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
//如果未登录,没有权限则调用该EntryPoint
.authenticationEntryPoint(authenticationEntryPoint)
// 无状态的Session机制(即Spring不使用HTTPSession),对于所有的请求都做权限校验
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
//关闭跨域保护
.and().csrf().disable();
//把自己写的2个filter加入到过滤器链中
http.addFilterBefore(jwtLoginFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilter(jwtAuthenticationFilter());
}
}
工具类:
package com.example.springsecurityjwtdemo.util;
import com.example.springsecurityjwtdemo.exception.InvalidJwtTokenException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author 阮胜
* @date 2018/7/5 21:21
*/
@Component
public class JwtTokenUtil implements Serializable {
private static final long serialVersionUID = -3301605591108950415L;
public static final String USERNAME = "username";
public static final String ROLE = "role";
public static final String CREATED_DATE = "createdDate";
private static final String SECRET = "jwt_secret";
private static final int EXPIRED_TIME_SECONDS = 60 * 60 * 24 * 7;
public JwtToken parseJwtToken(String token) throws InvalidJwtTokenException {
Claims claims = obtainClaims(token);
if (claims == null) {
throw new InvalidJwtTokenException();
}
return new JwtToken(claims.get(USERNAME).toString(), claims.get(ROLE).toString(), claims.get(CREATED_DATE, Date.class));
}
public String obtainUsername(String token) {
String username;
try {
final Claims claims = obtainClaims(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
public Date obtainExpiredDate(String token) {
Date expiration;
try {
final Claims claims = obtainClaims(token);
expiration = claims.getExpiration();
} catch (Exception e) {
expiration = null;
}
return expiration;
}
private Claims obtainClaims(String token) {
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
public Date generateExpirationDate() {
long expired = System.currentTimeMillis() + EXPIRED_TIME_SECONDS * 1000;
return new Date(expired);
}
private boolean isTokenExpired(String token) {
final Date expiration = obtainExpiredDate(token);
return expiration.after(new Date());
}
public String generateToken(UserDetails userDetails) {
return generateToken(
new JwtToken(userDetails.getUsername()
, userDetails.getAuthorities().iterator().next().toString()
, new Date()));
}
private String generateToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate())
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
public String generateToken(JwtToken jwtToken) {
HashMap<String, Object> tokenMap = new HashMap<>(3);
tokenMap.put(JwtTokenUtil.USERNAME, jwtToken.getUsername());
tokenMap.put(JwtTokenUtil.CREATED_DATE, jwtToken.getExpiredDate());
tokenMap.put(JwtTokenUtil.ROLE, jwtToken.getRole());
return generateToken(tokenMap);
}
public boolean validateToken(String token) {
Date expiredDate = obtainExpiredDate(token);
return expiredDate != null && expiredDate.after(new Date());
}
}
package com.example.springsecurityjwtdemo.util;
import lombok.Data;
import java.util.Date;
/**
* @author 阮胜
* @date 2018/7/5 20:54
*/
@Data
public class JwtToken {
private String username;
private String role;
private Date expiredDate;
public JwtToken() {
}
public JwtToken(String username, String role, Date expiredDate) {
this.username = username;
this.role = role;
this.expiredDate = expiredDate;
}
}
来源:https://www.cnblogs.com/cearnach/p/9288971.html