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
    即可。

  • 相关阅读:
    h5红包雨
    Reflect
    el-dialog对话弹框中根据后台数据无限制添加el-select标签,并进行展示,搜索,删除
    jQuery伪分页效果
    canvas实现验证码
    jQuery四叶草菜单效果,跟360杀毒软件差不多
    事件
    传参
    在shell script中进行数值运算的两种方法
    为maven插件设置参数的三种方法
  • 原文地址:https://www.cnblogs.com/c1024/p/11012056.html
Copyright © 2011-2022 走看看