zoukankan      html  css  js  c++  java
  • SpringBoot2.0整合SpringSecurity实现WEB JWT认证

    相信很多做技术的朋友都做过前后端分离项目,项目分离后认证就靠JWT,费话不多说,直接上干活(写的不好还请多多见谅,大牛请绕行)

    直接上代码,项目为Maven项目,结构如图:

    包分类如下:

    com.api.config  相关配置类

    com.api.ctrl  controller层

    com.api.entity  相关实体类

    com.api.repo   jpa仓库相关

    com.api.serice  service层相关

    ApiApplication 为启动类

    主要配置核心类如下:

    JWTAuthenticationFilter 

    package com.api.config;
    
    import com.api.entity.User;
    import com.api.repo.UserRepo;
    import io.jsonwebtoken.Jwts;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.ArrayList;
    
    public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
    
        private UserRepo userRepo;
    
        public JWTAuthenticationFilter(AuthenticationManager authenticationManager,UserRepo userRepo) {
            super(authenticationManager);
            this.userRepo = userRepo;
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
    
            String header = request.getHeader("Authorization");
            //如果不包含Bearer则退出
            if(header != null && !header.startsWith("Bearer")){
                chain.doFilter(request,response);
                return;
            }
    
            UsernamePasswordAuthenticationToken authenticationToken = getAuthentication(request);
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            chain.doFilter(request,response);
        }
    
        private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
            String token = request.getHeader("Authorization");
            if (token != null) {
                // parse the token.
                String user = Jwts.parser()
                        .setSigningKey("HSMyJwtSecret".getBytes())
                        .parseClaimsJws(token.replace("Bearer ", ""))
                        .getBody()
                        .getSubject();
                if (user != null) {
                    Integer userId = Integer.valueOf(user.split(":")[0]);
                    User currUser = userRepo.findById(userId).orElse(null);
                    if(currUser != null){
                        return new UsernamePasswordAuthenticationToken(currUser, null, new ArrayList<>());
                    }
                    return new UsernamePasswordAuthenticationToken(new User(), null, new ArrayList<>());
                }
            }
            return null;
        }
    }
    
    JWTLoginFilter
    package com.api.config;
    
    import com.api.entity.User;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    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.UsernamePasswordAuthenticationFilter;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Date;
    
    public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {
    
        private AuthenticationManager authenticationManager;
    
        public JWTLoginFilter(AuthenticationManager authenticationManager){
            this.authenticationManager = authenticationManager;
        }
    
        
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
            try {
                User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
                return authenticationManager.authenticate(
                  new UsernamePasswordAuthenticationToken(
                          user.getUsername(),
                          user.getPassword(),
                          new ArrayList<>()
                  )
                );
    
            }catch (Exception e){
                throw new RuntimeException(e);
            }
        }
    
    
        @Override
        protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
            String token = Jwts.builder()
                    .setSubject(((JwtUser) authResult.getPrincipal()).getUsername())
                    .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 24 * 1000))
                    .signWith(SignatureAlgorithm.HS256,"HSMyJwtSecret".getBytes())
                    .compact();
            response.addHeader("Authorization", "Bearer " + token);
            response.getOutputStream().println(token);
        }
    }
    
    MyUserDetailService
    package com.api.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.stereotype.Component;
    
    import java.util.Collection;
    
    @Component
    public class MyAuthencationProvider implements AuthenticationProvider {
    
        @Autowired
        private MyUserDetailService myUserDetailService;
    
        
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            String username = authentication.getPrincipal().toString();
            JwtUser jwtUser = (JwtUser) myUserDetailService.loadUserByUsername(username);
            Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
            return new UsernamePasswordAuthenticationToken(jwtUser, jwtUser.getPassword(), authorities);
        }
    
        @Override
        public boolean supports(Class<?> aClass) {
            return true;
        }
    }
    
    MyUserDetailService
    package com.api.config;
    
    import com.api.entity.User;
    import com.api.repo.UserRepo;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyUserDetailService implements UserDetailsService {
    
        @Autowired
        private UserRepo userRepo;
    
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            User user = userRepo.findFirstByUsername(s);
            if(user != null){
                JwtUser jwtUser = new JwtUser(String.format("%s:%s",String.valueOf(user.getId()),user.getUsername()),user.getPassword());
                return jwtUser;
            }
            throw new UsernameNotFoundException("用户名未找到");
        }
    }
    
    
    
    WebSecurityConfig
    package com.api.config;
    
    import com.api.repo.UserRepo;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import org.springframework.http.HttpMethod;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    @Order(-1)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private MyAuthencationProvider myAuthencationProvider;
        @Autowired
        private UserRepo userRepo;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and().csrf().disable().authorizeRequests()
                    .antMatchers(HttpMethod.POST, "/register").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .addFilter(new JWTLoginFilter(authenticationManager()))
                    .addFilter(new JWTAuthenticationFilter(authenticationManager(),userRepo));
        }
    
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(myAuthencationProvider);
        }
    
    
    }
    
    JwtUser
    package com.api.config;
    
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    
    import java.util.Collection;
    
    public class JwtUser implements UserDetails {
    
        private String username;
        private String password;
    
    
        public JwtUser(String username,String password){
            this.username = username;
            this.password = password;
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return null;
        }
    
        @Override
        public String getPassword() {
            return password;
        }
    
        @Override
        public String getUsername() {
            return username;
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return false;
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return false;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return false;
        }
    
        @Override
        public boolean isEnabled() {
            return false;
        }
    
    }
    
    MyMvcConfigurer
    package com.api.config;
    
    import org.springframework.boot.autoconfigure.AutoConfigureBefore;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.access.SecurityConfig;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    @AutoConfigureBefore(SecurityConfig.class)
    public class MyMvcConfigurer implements WebMvcConfigurer {
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("*")
                    .allowedHeaders("*")
                    .allowCredentials(true)
                    .maxAge(3600);
        }
    }
    

    以上为config包下全部内容

    项目POM.xml配置如下

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.1.0.RELEASE</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>com.api</groupId>
    	<artifactId>api</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>api</name>
    	<description>Demo project for Spring Boot</description>
    
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-redis</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-jdbc</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-jpa</artifactId>
    		</dependency>
    
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-security</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    			<scope>runtime</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<optional>true</optional>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    
    		<dependency>
    			<groupId>com.github.wenhao</groupId>
    			<artifactId>jpa-spec</artifactId>
    			<version>3.2.3</version>
    		</dependency>
    
    		<dependency>
    			<groupId>cn.hutool</groupId>
    			<artifactId>hutool-all</artifactId>
    			<version>4.3.1</version>
    		</dependency>
    
    		<dependency>
    			<groupId>io.jsonwebtoken</groupId>
    			<artifactId>jjwt</artifactId>
    			<version>0.7.0</version>
    		</dependency>
    
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<version>3.5.1</version>
    				<configuration>
    					<compilerArgs>
    						<arg>-verbose</arg>
    						<arg>-Xlint:all,-options,-path</arg>
    					</compilerArgs>
    					<source>1.8</source>
    					<target>1.8</target>
    				</configuration>
    			</plugin>
    
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    			<plugin>
    				<artifactId>maven-jar-plugin</artifactId>
    				<configuration>
    					<archive>
    						<manifest>
    							<addClasspath>true</addClasspath>
    							<classpathPrefix>lib/</classpathPrefix>
    							<mainClass>com.api.ApiApplication</mainClass>
    						</manifest>
    					</archive>
    				</configuration>
    
    			</plugin>
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-resources-plugin</artifactId>
    				<configuration>
    					<delimiters>
    						<delimiter>@</delimiter>
    						<delimiter>#{*}</delimiter>
    						<delimiter>#</delimiter>
    					</delimiters>
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>
    
    	<repositories>
    		<repository>
    			<id>spring-snapshots</id>
    			<name>Spring Snapshots</name>
    			<url>https://repo.spring.io/snapshot</url>
    			<snapshots>
    				<enabled>true</enabled>
    			</snapshots>
    		</repository>
    		<repository>
    			<id>spring-milestones</id>
    			<name>Spring Milestones</name>
    			<url>https://repo.spring.io/milestone</url>
    		</repository>
    	</repositories>
    	<pluginRepositories>
    		<pluginRepository>
    			<id>spring-snapshots</id>
    			<name>Spring Snapshots</name>
    			<url>https://repo.spring.io/snapshot</url>
    			<snapshots>
    				<enabled>true</enabled>
    			</snapshots>
    		</pluginRepository>
    		<pluginRepository>
    			<id>spring-milestones</id>
    			<name>Spring Milestones</name>
    			<url>https://repo.spring.io/milestone</url>
    		</pluginRepository>
    	</pluginRepositories>
    
    </project>
    

    以下为其他包结构以及类文件

    以上配置成功后即可以POST方式访问

    http://localhost:8080/login?username=xxx&password=xx 认证成功后会在返回jwt,下次请求认证的资源在header里边带上Authorization Bearer xxxxxx
    即可。

  • 相关阅读:
    poj 3321 Apple Tree
    hdu 1520 Anniversary party
    Light OJ 1089 Points in Segments (II)
    Timus 1018 Binary Apple Tree
    zoj 3299 Fall the Brick
    HFUT 1287 法默尔的农场
    Codeforces 159C String Manipulation 1.0
    GraphQL + React Apollo + React Hook 大型项目实战(32 个视频)
    使用 TypeScript & mocha & chai 写测试代码实战(17 个视频)
    GraphQL + React Apollo + React Hook + Express + Mongodb 大型前后端分离项目实战之后端(19 个视频)
  • 原文地址:https://www.cnblogs.com/c1024/p/11012056.html
Copyright © 2011-2022 走看看