Day 28 - Spring Security (五) JwtAuthenticationProvider

实作

新增依赖

<!-- JWT -->
<dependency>
	<groupId>io.jsonwebtoken</groupId>
	<artifactId>jjwt-api</artifactId>
	<version>0.11.2</version>
</dependency>

<dependency>
	<groupId>io.jsonwebtoken</groupId>
	<artifactId>jjwt-impl</artifactId>
	<version>0.11.2</version>
	<scope>runtime</scope>
</dependency>

<dependency>
	<groupId>io.jsonwebtoken</groupId>
	<artifactId>jjwt-jackson</artifactId>
	<version>0.11.2</version>
	<scope>runtime</scope>
</dependency>

新增工具类

package com.example.iThomeIronMan.util;

import java.security.Key;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

public class JwtUtil {

	private static final long EXPIRATIONTIME = 432_000_000;     // 5天
	private static final String TOKEN_PREFIX = "Bearer";        // Token前缀
	private static final String HEADER_STRING = "Authorization";// 存放Token的Header Key
	private static final String KEY = "VincentIsRunningBlogForProgrammingBeginnerSpringSecurityAndJWT";	//给定一组密钥,用来解密以及加密使用
	private static final Key secretKey = Keys.hmacShaKeyFor(KEY.getBytes());
	
	public static void generateToken(HttpServletResponse response, String account) {
						
		Claims claims = Jwts.claims();
		claims.put("account", account);
		claims.setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME));
		
		String token = Jwts.builder().setClaims(claims).signWith(secretKey).compact();
		response.setContentType("application/json");
		response.setHeader(HEADER_STRING, token);
	}
	
	public static Map<String, Object> parseToken(HttpServletRequest request) {

    // 从request的header拿回token
    String token = request.getHeader(HEADER_STRING);
    if(token != null) {
			JwtParser parser = Jwts.parserBuilder().setSigningKey(secretKey).build();
			Claims claims = parser.parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();

	        return claims.entrySet().stream()
				        			 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
		}
		return null;
	}
}

修改CustomAuthenticationSuccessHandler

package com.example.iThomeIronMan.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import com.example.iThomeIronMan.util.JwtUtil;

public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
	
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {
		// TODO Auto-generated method stub
		
		JwtUtil.generateToken(response, authentication.getName());
	  response.sendRedirect("/information");
	}

}

新增JwtAuthenticationFilter

package com.example.iThomeIronMan.filter;

import java.io.IOException;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.web.filter.GenericFilterBean;

import com.example.iThomeIronMan.util.JwtUtil;

public class JwtAuthenticationFilter extends GenericFilterBean {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub

		HttpServletRequest req = (HttpServletRequest) request;

		String uri = new String(req.getRequestURI());
		
		// 放行所有静态档案
		if(uri.contains("/css") || uri.contains("/images") || uri.contains("/js")) {
			chain.doFilter(request, response);
			return ;
		}

		if(uri.contains("/login") || uri.contains("/register")) {
			chain.doFilter(request, response);
			return ;
		}

    String token = req.getHeader("Authorization");
		//验证token,获得授权
		Map<String, Object> claims = JwtUtil.parseToken(req);
		if(claims != null) {
			System.err.println(claims);
			chain.doFilter(request, response);
		}
	}

}

修改SecurityConfig

package com.example.iThomeIronMan.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.example.iThomeIronMan.filter.JwtAuthenticationFilter;
import com.example.iThomeIronMan.security.CustomAuthenticationFailureHandler;
import com.example.iThomeIronMan.security.CustomAuthenticationProvider;
import com.example.iThomeIronMan.security.CustomAuthenticationSuccessHandler;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private UserDetailsService userDetailsService;

	@Autowired
	private CustomAuthenticationProvider authProvider;
	
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		// TODO Auto-generated method stub
		auth.authenticationProvider(authProvider);
	}

	@Override
    protected void configure(HttpSecurity http) throws Exception {
		// TODO Auto-generated method stub
        http.authorizeRequests()
        	// 设定放行名单
			.antMatchers("/login", "/register").permitAll()
            // 其余路径皆须进行验证
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/login").loginProcessingUrl("/login").usernameParameter("account").passwordParameter("password")
            .successHandler(new CustomAuthenticationSuccessHandler())
            .failureHandler(new CustomAuthenticationFailureHandler())
            .and()
            .logout().logoutUrl("/logout")
            .and()
            .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            // 关闭CSRF(跨站请求伪造)攻击的防护,这样才不会拒绝外部直接对API 发出的请求,例如Postman 与前端
            .csrf().disable();
    }

	@Override
	public void configure(WebSecurity web) throws Exception {
		// TODO Auto-generated method stub
		web.ignoring().antMatchers("/css/**", "/images/**", "/js/**");
	}

}

<<:  Day28. 虽然今年是2021,但我们要做2048(2)

>>:  [Day 30] 完赛心得:你的前端之旅还尚未结束

【C language part 1】浅谈 C 语言-认识C

在台科大大一的课程当了助教,也写了不少给大一新生看的讲义。 这边就分享一下当了两年助教的讲义内容给各...

找LeetCode上简单的题目来撑过30天啦(DAY6)

今天尝试了前几天被我放弃的题目,过一两天後果然比较有感觉,花了一点时间还是完成了呢,心情不错 题号:...

将质化转为量化的数据分析

不管是问卷分析还是在看用户的使用资料,都充斥着许多密密麻麻的资料,这些值化的资料最後都会转换成量化的...

[30天 Vue学好学满 DAY11] v-on

v-on 监听DOM并进行触发 v-on: -> 简写 @ v-on:click="...

企划实现(11)

FB登入 以上功能都完成後就要开始环境的建置了 第一步:下载android studio sdk(如...