zoukankan      html  css  js  c++  java
  • springboot成神之——basic auth和JWT验证结合

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

    目录结构

    依赖

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
    </dependency>
    		
    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>auth0</artifactId>
        <version>1.8.0</version>
    </dependency>
    
    <dependency>
    	<groupId>com.auth0</groupId>
    	<artifactId>auth0-spring-security-api</artifactId>
    	<version>1.1.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.json</groupId>
    	<artifactId>json</artifactId>
    	<version>20180813</version>
    </dependency>
    
    <dependency>
    	<groupId>org.glassfish</groupId>
    	<artifactId>javax.xml.bind</artifactId>
    	<version>10.0-b28</version>
    </dependency>
    

    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<AuthenticationManagerBuilder> 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<String, String> result = new HashMap<String, String>();  
            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";
        }
    }
    

    前端测试

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
        <script>
            axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 
            
    
            axios.post('http://localhost:9001/login', {
                username: 'yejiawei',
                password: '234'
            }).then(function (response) {
                localStorage.setItem("token", response.data.result)
            }).catch(function (error) {
                console.log(error);
            }).then(function () {
            });
    
            // axios.get('http://localhost:9001/AuthTest', {
            //     headers: {
            //         "Authorization": localStorage.getItem("token")
            //     }
            // }).then(function (response) {
            //     console.log(response.data);
            // }).catch(function (error) {
            //     console.log(error);
            // }).then(function () {
            // });
    
            
        </script>
    </head>
    <body>
    </body>
    </html>
    
  • 相关阅读:
    FreeCAD框架解析
    Python源码的编译与加密
    centos 8及以上安装mysql 8.0
    浮点数运算丢失精度
    使用 Nginx 代理内网 GitLab 并确保 SSH / HTTP 克隆地址正确
    如何实现一个简易版的 Spring
    Spring 是如何造出一个 Bean 的
    从CPU缓存看缓存的套路
    Java 集合类 List 的那些坑
    react 项目中使用antd框架,对导航多层渲染
  • 原文地址:https://www.cnblogs.com/ye-hcj/p/9634893.html
Copyright © 2011-2022 走看看