springboot成神之——basic auth和JWT验证结合

  • 本文介绍basic auth和JWT验证结合
    • 目录结构
    • 依赖
    • config配置文件WebSecurityConfig
    • filter过滤器JWTLoginFilter
    • filter过滤器JWTAuthenticationFilter
    • service中的TokenAuthenticationService
    • 启动文件DemoApplication
    • Controller中的TestController
    • 前端测试

本文介绍basic auth和JWT验证结合

目录结构

springboot成神之——basic auth和JWT验证结合_第1张图片

依赖


    io.jsonwebtoken
    jjwt
    0.9.1

        

    com.auth0
    auth0
    1.8.0



    com.auth0
    auth0-spring-security-api
    1.1.0



    org.springframework.boot
    spring-boot-starter-security



    org.json
    json
    20180813



    org.glassfish
    javax.xml.bind
    10.0-b28

config配置文件WebSecurityConfig

package com.springlearn.learn.config;

import com.springlearn.learn.filter.JWTAuthenticationFilter;
import com.springlearn.learn.filter.JWTLoginFilter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;



@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable();
        // 所有的请求都要验证
        http.authorizeRequests()
        .antMatchers("/").permitAll() // 访问 "/" 无需验证
        .antMatchers(HttpMethod.POST, "/login").permitAll() // 访问 "/login" 无需token即可进入
        .antMatchers(HttpMethod.GET, "/login").permitAll() 
        .anyRequest()
        .authenticated()
        .and()
        .addFilterBefore( // 添加验证过滤器
            new JWTLoginFilter("/login", authenticationManager()),
            UsernamePasswordAuthenticationFilter.class
        )
        .addFilterBefore(
            new JWTAuthenticationFilter(), 
            UsernamePasswordAuthenticationFilter.class
        );
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        return bCryptPasswordEncoder;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        String password = "234";
        String encrytedPassword = this.passwordEncoder().encode(password);
        System.out.println("Encoded password = " + encrytedPassword);

        // 这里使用写死的验证,你可以在这里访问数据库
        InMemoryUserDetailsManagerConfigurer mngConfig = auth.inMemoryAuthentication();
        
        UserDetails u1 = User.withUsername("yejiawei").password(encrytedPassword).roles("ADMIN").build();
        UserDetails u2 = User.withUsername("donglei").password(encrytedPassword).roles("USER").build();

        mngConfig.withUser(u1);
        mngConfig.withUser(u2);
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
        .allowedHeaders("*");
    }
}

filter过滤器JWTLoginFilter

package com.springlearn.learn.filter;


import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.stream.Collectors;

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

import com.springlearn.learn.service.TokenAuthenticationService;

import org.json.JSONObject;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter{
    public JWTLoginFilter(String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        
        // get方式获取参数
        // String username = request.getParameter("username");
        // String password = request.getParameter("password");
        
        // post方式获取数据
        String s = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        JSONObject jsonObject = new JSONObject(s);  
        HashMap result = new HashMap();  
        String key = null;
        Iterator keys = jsonObject.keys();
        while(keys.hasNext()) {
            key = (String) keys.next();  
            result.put(key, jsonObject.getString(key));  
        }
        
        System.out.printf("JWTLoginFilter.attemptAuthentication: username/password= %s,%s", result.get("username"), result.get("password"));
        System.out.println();
    
        return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(result.get("username"), result.get("password"), Collections.emptyList()));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
            Authentication authResult) throws IOException, ServletException {
 
        System.out.println("JWTLoginFilter.successfulAuthentication:");
 
        // Write Authorization to Headers of Response.
        TokenAuthenticationService.addAuthentication(response, authResult.getName());
 
        String authorizationString = response.getHeader("Authorization");
 
        System.out.println("Authorization String=" + authorizationString);
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {

        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getOutputStream().println((new JSONObject(){{
            put("status", 500);
            put("message", "Internal Server Error!!!");
            put("result", JSONObject.NULL);
        }}).toString());
    }
}

filter过滤器JWTAuthenticationFilter

package com.springlearn.learn.filter;

import java.io.IOException;

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

import com.springlearn.learn.service.TokenAuthenticationService;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;

public class JWTAuthenticationFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
         
        System.out.println("JWTAuthenticationFilter.doFilter");
         
        Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest) servletRequest);
         
        SecurityContextHolder.getContext().setAuthentication(authentication);
         
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

service中的TokenAuthenticationService

package com.springlearn.learn.service;

import java.io.IOException;
import java.util.Collections;
import java.util.Date;

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

import org.json.JSONObject;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

public class TokenAuthenticationService {

    static final long _expiretime = 864_000_000; 
    static final String _secret = "ThisIsASecret";
    static final String _token_prefix = "Bearer";
    static final String _header_string = "Authorization";

    public static void addAuthentication(HttpServletResponse res, String username) throws IOException {
        String JWT = 
                Jwts.builder()
                .setSubject(username)
                .setExpiration(new Date(System.currentTimeMillis() + _expiretime))
                .signWith(SignatureAlgorithm.HS512, _secret).compact();

        res.addHeader(_header_string, _token_prefix + " " + JWT);
        res.setContentType("application/json");
        res.setStatus(HttpServletResponse.SC_OK);
        res.getOutputStream().println((new JSONObject(){{
            put("status", 0);
            put("message", "");
            put("result", JWT);
        }}).toString());

    }

    public static Authentication getAuthentication(HttpServletRequest request) {
        String token = request.getHeader(_header_string);
        if (token != null) {
            // parse the token.
            String user = Jwts.parser().setSigningKey(_secret).parseClaimsJws(token.replace(_token_prefix, "")).getBody()
                    .getSubject();

            return user != null ? new UsernamePasswordAuthenticationToken(user, null, Collections.emptyList()) : null;
        }
        return null;
    }
}

启动文件DemoApplication

package com.springlearn.learn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

Controller中的TestController

package com.springlearn.learn.controller;

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

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @ResponseBody
    @RequestMapping(value = "/AuthTest", method = RequestMethod.GET)
    public String AuthTest(HttpServletRequest request, HttpServletResponse response) {
        return "OK";
    }

    @ResponseBody
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String Login(@RequestBody Object user, HttpServletRequest request, HttpServletResponse response) {
        return "OK";
    }
}

前端测试




    
    
    
    Document
    
    



你可能感兴趣的:(springboot成神之——basic auth和JWT验证结合)