How SpringBoot combines JWT to implement login permission control
First we need to import the jwt package used:
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.8.0</version> </dependency> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.2.0</version> </dependency>
1. Prepare LoginUser (to store login user information) and JwtUser
LoginUser.java
public class LoginUser { private Integer userId; private String username; private String password; private String role; 生成getter和setter...... }
JwtUser.java
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; import java.util.Collections; public class JwtUser implements UserDetails{ private Integer id; private String username; private String password; private Collection<? extends GrantedAuthority> authorities; public JwtUser(){ } public JwtUser(LoginUser loginUser){ this.id = loginUser.getUserId(); this.username = loginUser.getUsername(); this.password = loginUser.getPassword(); authorities = Collections.signleton(new SimpleGrantedAuthority(loginUser.getRole())); } @Override public Collection<? extends GrantedAuthority> getAuthorities(){ return authorities; } @Override public String getPassword(){ return password; } @Override public String getUsername(){ return username; } //账号是否未过期 @Override public boolean isAccountNonExpired(){ return true; } //账号是否未锁定 @Override public boolean isAccountNonLocked(){ return true } //账号凭证是否未过期 @Override public boolean isCredentialsNonExpired(){ return true; } @Override public boolean isEnabled(){ return true; } }
2. Prepare JwtTokenUtils
import com.bean.JwtUser; import io.jsonwebtoken.*; import org.springframework.security.core.userdetails.UserDetails; import java.util.Date; import java.util.HashMap; import java.util.Map; public class JwtTokenUtils { public static final String TOKEN_HEADER = "Authorization"; public static final String TOKEN_PREFIX = "Bearer "; public static final String SECRET = "jwtsecret"; public static final String ISS = "echisan"; private static final Long EXPIRATION = 60 * 60 * 3;//过期时间3小时 private static final String ROLE = "role"; //创建token public static String createToken(String username, String role, boolean isRememberMe){ Map map = new HashMap(); map.put(ROLE, role); return Jwts.builder() .signWith(SignatureAlgorithm.HS512, SECRET) .setClaims(map) .setIssuer(ISS) .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000)) .compact(); } //从token中获取用户名(此处的token是指去掉前缀之后的) public static String getUserName(String token){ String username; try { username = getTokenBody(token).getSubject(); } catch ( Exception e){ username = null; } return username; } public static String getUserRole(String token){ return (String) getTokenBody(token).get(ROLE); } private static Claims getTokenBody(String token){ Claims claims = null; try{ claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody(); } catch(ExpiredJwtException e){ e.printStackTrace(); } catch(UnsupportedJwtException e){ e.printStackTrace(); } catch(MalformedJwtException e){ e.printStackTrace(); } catch(SignatureException e){ e.printStackTrace(); } catch(IllegalArgumentException e){ e.printStackTrace(); } } //是否已过期 public static boolean isExpiration(String token){ try{ return getTokenBody(token).getExpiration().before(new Date()); } catch(Exception e){ e.printStackTrace; } return true; } }
3. Prepare JWTAuthenticationFilter (verify login), JWTAuthorizationFilter (authentication authority) and UserDetailsServiceImpl class (check database to match account password)
1.JWTAuthenticationFilter.java (Verify login)
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter{ private AuthenticationManager authenticationManager; public JWTAuthenticationFilter(AuthenticationManager authenticationManager){ this.authenticationManager = authenticationManager; setAuthenticationFailureHandler(new FailHandler());//设置账号密码错误时的处理方式 } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException{ //从输入流中获取登录的信息 String username = request.getParameter("username"); String password = request.getParameter("password"); return authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(username, password, new ArrayList<>()) ); } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult ) throws IOException, ServletException{ JwtUser jwtUser = (JwtUser) authResult.getPrincipal(); Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities(); String role = ""; for(GrantedAuthority authority : authorities){ role = authority.getAuthority(); } String token = JwtTokenUtils.createToken(jwtUser.getUsername, role, false); //返回创建成功的token //但是这里创建的token只是单纯的token,按照jwt的规定, //最后请求的格式应该是 “Bearer token“。 response.addHeader(JwtTokenUtils.TOKEN_HEADER, JwtTokenUtils.TOKEN_PREFIX + token); } //@Override //protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, // AuthenticationException failed) throws IOException, ServletException { // response.getWriter().write("authentication failed, reason: " + failed.getMessage()); //} }
2.JWTAuthorizationFilter.java (Authentication authority)
public class JWTAuthorizationFilter extends BasicAuthenticationFilter{ public JWTAuthorizationFilter(AuthenticationManager authenticationManager){ super(authenticationManager); } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String tokenHeader = request.getHeader(JwtTokenUtils.TOKEN_HEADER); //如果请求头中没有Authorization信息则直接放行了 if(tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtils.TOKEN_PREFIX)){ chain.doFilter(request, response); return; } //如果请求头中有token,则进行解析,并且设置认证信息 if(!JwtTokenUtils.isExpiration(tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, “”))){ SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader)); } chain.doFilter(request, response); } private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader){ String token = tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, “”); String username = JwtTokenUtils.getUserName(token); if(username != null){ return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>()); } return null; } }
3.UserDetailsServiceImpl.java (Check the database to match the account password)
import org.springframework.security.core.userdetails.UserDetailsService; @Service public class UserDetailsServiceImpl implements UserDetailsService{ @Autowired UserMapper userMapper; public BCryptPasswordEncoder bCryptPasswordEncoder(){ return new BCryptPasswordEncoder(); } @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { LoginUser loginUser = usersMapper.selectByUserAccount(s); loginUser.setPassword(bCryptPasswordEncoder().encode(loginUser.getPassword())); return new JwtUser(loginUser); } }
4. FailHandler (handling method when account password is incorrect)
public class FailHandler extends SimpleUrlAuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { String errorMsg = exception.getMessage(); if(exception instanceof BadCredentialsException){ errorMsg = "用户名或密码错误"; } response.setHeader("content-type", "application/json"); response.getOutputStream().write(JSONObject.fromObject(new AjaxResult(errorMsg, false)).toString().getBytes("utf-8")); } }
5. Configuring SecurityConfig
This class specifies relevant information about permissions
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired private UserDetailsService userDetailsService; @Bean public BCryptPasswordEncoder bCryptPasswordEncoder(){ return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); } @Override public void configure(WebSecurity web) throws Exception{ web.ignoring().antMatchers("/static/**"); } @Override protected void configure(HttpSecurity http) throws Exception{ http.cors().and().csrf().disable() .authorizeRequests() .antMatchers(HttpMethod.POST, "/login").permitAll()//都可以访问 .antMatchers("/").permitAll() .antMatchers("/index.html").permitAll() .antMatchers("/*.js").permitAll() .antMatchers("/*.css").permitAll() .antMatchers("/*.png").permitAll() .antMatchers("/*.svg").permitAll() .antMatchers("/*.woff").permitAll() .antMatchers("/*.ttf").permitAll() .antMatchers("/*.eot").permitAll() .antMatchers("/test/*").permitAll()//对接口的权限控制,表示对于"/test"路径下的所有接口无需登录也可以访问 .antMatchers("/swagger-ui.html", "/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/webjars/**", "/swagger-resources/configuration/ui").permitAll()//表示对swagger页面放行 .anyRequest().authenticated()//表示其余所有请求需要登陆之后才能访问 .and() .addFilter(new JWTAuthenticationFilter(authenticationManager())) .addFilter(new JWTAuthorizationFilter(authenticationManager())) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); } @Bean CorsConfigurationSource corsConfigurationSource() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues()); return source; } }
The above is the detailed content of How SpringBoot combines JWT to implement login permission control. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Introduction to Jasypt Jasypt is a java library that allows a developer to add basic encryption functionality to his/her project with minimal effort and does not require a deep understanding of how encryption works. High security for one-way and two-way encryption. , standards-based encryption technology. Encrypt passwords, text, numbers, binaries... Suitable for integration into Spring-based applications, open API, for use with any JCE provider... Add the following dependency: com.github.ulisesbocchiojasypt-spring-boot-starter2. 1.1Jasypt benefits protect our system security. Even if the code is leaked, the data source can be guaranteed.

1. Redis implements distributed lock principle and why distributed locks are needed. Before talking about distributed locks, it is necessary to explain why distributed locks are needed. The opposite of distributed locks is stand-alone locks. When we write multi-threaded programs, we avoid data problems caused by operating a shared variable at the same time. We usually use a lock to mutually exclude the shared variables to ensure the correctness of the shared variables. Its scope of use is in the same process. If there are multiple processes that need to operate a shared resource at the same time, how can they be mutually exclusive? Today's business applications are usually microservice architecture, which also means that one application will deploy multiple processes. If multiple processes need to modify the same row of records in MySQL, in order to avoid dirty data caused by out-of-order operations, distribution needs to be introduced at this time. The style is locked. Want to achieve points

Springboot reads the file, but cannot access the latest development after packaging it into a jar package. There is a situation where springboot cannot read the file after packaging it into a jar package. The reason is that after packaging, the virtual path of the file is invalid and can only be accessed through the stream. Read. The file is under resources publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

With the development of the Internet, more and more websites and applications need to provide API interfaces for data interaction. In this case, API authentication and encryption become very important issues. As a popular authentication and encryption mechanism, JWT and JWE are increasingly used in PHP. Well, this article will explain how to use JWT and JWE for API authentication and encryption in PHP. Basic concepts of JWT JWT stands for JSONWe

JWT (JSONWebToken) is a lightweight authentication and authorization mechanism that uses JSON objects as security tokens to securely transmit user identity information between multiple systems. ThinkPHP6 is an efficient and flexible MVC framework based on PHP language. It provides many useful tools and functions, including JWT authentication mechanism. In this article, we will introduce how to use ThinkPHP6 for JWT authentication to ensure the security and reliability of web applications

SpringBoot and SpringMVC are both commonly used frameworks in Java development, but there are some obvious differences between them. This article will explore the features and uses of these two frameworks and compare their differences. First, let's learn about SpringBoot. SpringBoot was developed by the Pivotal team to simplify the creation and deployment of applications based on the Spring framework. It provides a fast, lightweight way to build stand-alone, executable

When Springboot+Mybatis-plus does not use SQL statements to perform multi-table adding operations, the problems I encountered are decomposed by simulating thinking in the test environment: Create a BrandDTO object with parameters to simulate passing parameters to the background. We all know that it is extremely difficult to perform multi-table operations in Mybatis-plus. If you do not use tools such as Mybatis-plus-join, you can only configure the corresponding Mapper.xml file and configure The smelly and long ResultMap, and then write the corresponding sql statement. Although this method seems cumbersome, it is highly flexible and allows us to

1. Customize RedisTemplate1.1, RedisAPI default serialization mechanism. The API-based Redis cache implementation uses the RedisTemplate template for data caching operations. Here, open the RedisTemplate class and view the source code information of the class. publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations, BeanClassLoaderAware{//Declare key, Various serialization methods of value, the initial value is empty @NullableprivateRedisSe
