本篇介绍最简单的Security整合Jwt实现用户登入
根据上几篇文章的哦!!!
不明白的可以看上几篇文章看下
创建Jwt工具类
JwtUtil类
public class JwtUtil {
public static final String TOKEN_HEADER = "Authorization";
public static final String TOKEN_PREFIX = "HE ";
public static final String SECRET = "jwtsecret";
public static final String ISS = "echisan";
private static final Long EXPIRATION = 60 * 60 * 3L; //过期时间3小时
private static final String ROLE = "role";
//创建token
public static String createToken(String username, String role, boolean isRememberMe){
Map map = new HashMap();
map.put(ROLE, role);
return Jwts.builder()
.signWith(SignatureAlgorithm.HS512, SECRET)
.setClaims(map)
.setIssuer(ISS)
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))
.compact();
}
//从token中获取用户名(此处的token是指去掉前缀之后的)
public static String getUserName(String token){
String username;
try {
username = getTokenBody(token).getSubject();
} catch ( Exception e){
username = null;
}
return username;
}
public static String getUserRole(String token){
return (String) getTokenBody(token).get(ROLE);
}
private static Claims getTokenBody(String token){
Claims claims = null;
try{
claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
} catch(ExpiredJwtException e){
e.printStackTrace();
} catch(UnsupportedJwtException e){
e.printStackTrace();
} catch(MalformedJwtException e){
e.printStackTrace();
} catch(SignatureException e){
e.printStackTrace();
} catch(IllegalArgumentException e){
e.printStackTrace();
}
return claims;
}
//是否已过期
public static boolean isExpiration(String token){
try{
return getTokenBody(token).getExpiration().before(new Date());
} catch(Exception e){
System.out.println(e.getMessage());
}
return true;
}
配置用户资源处理器
jwtAccessDeniedHandler
@Component
public class jwtAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException, IOException {
System.out.println("用户访问没有授权资源");
System.out.println(e.getMessage());
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e==null? String.valueOf(ResultUtil.Error(401,"用户没有授权")) :e.getMessage());
}
}
配置用户资源授权处理
JwtAuthentication类 实现AuthenticationEntryPoint
@Component
public class JwtAuthentication implements AuthenticationEntryPoint{
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
System.out.println("用户访问资源没有携带正确的token");
System.out.println(e.getMessage());
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e == null ? "用户访问资源没有携带正确的token" : e.getMessage());
}
}
配置Jwt的Filter
创建一个FIlter来进行过滤Jwt的token
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 tokenHead=request.getHeader(JwtUtil.TOKEN_HEADER);
if(tokenHead==null|| !tokenHead.startsWith(JwtUtil.TOKEN_PREFIX)){
chain.doFilter(request,response);
return;
}
if(!JwtUtil.isExpiration(tokenHead.replace(JwtUtil.TOKEN_PREFIX,""))){
//设置上下文
UsernamePasswordAuthenticationToken authentication = getAuthentication(tokenHead);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
super.doFilterInternal(request, response, chain);
}
//获取用户信息
private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader){
String token = tokenHeader.replace(JwtUtil.TOKEN_PREFIX, "");
String username = JwtUtil.getUserName(token);
// 获得权限 添加到权限上去
String role = JwtUtil.getUserRole(token);
List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
roles.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return role;
}
});
if(username != null){
return new UsernamePasswordAuthenticationToken(username, null,roles);
}
return null;
}
public JwtAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
super(authenticationManager, authenticationEntryPoint);
}
}
在Security上面进行配置Filter
下面上SecurityConfig的配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
userDetailsService userDetailsService;
@Autowired
private jwtAccessDeniedHandler jwtAccessDeniedHandler;
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/**")
.permitAll()
.antMatchers("/").permitAll()
//login 不拦截
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
//授权
.and()
// 禁用session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 使用自己定义的拦截机制,拦截jwt
http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class)
//授权错误信息处理
.exceptionHandling()
//用户访问资源没有携带正确的token
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
//用户访问没有授权资源
.accessDeniedHandler(jwtAccessDeniedHandler);
}
@Bean
public PasswordEncoder passwordEncoder() {
//使用的密码比较方式
return new BCryptPasswordEncoder();
}
}
大功告成,这样就完成了整合