SpringBoot结合JWT怎么实现登录权限控制
来源:亿速云
时间:2024-04-10 21:06:33 104浏览 收藏
本篇文章给大家分享《SpringBoot结合JWT怎么实现登录权限控制》,覆盖了文章的常见基础知识,其实一个语言的全部知识点一篇文章是不可能说完的,但希望通过这些问题,让读者对自己的掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的掌握它。
首先我们需要导入使用到的jwt的包:
io.jsonwebtoken jjwt 0.8.0 com.auth0 java-jwt 3.2.0
一、准备LoginUser(存放登录用户信息) 和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; } }
二、准备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; } }
三、准备JWTAuthenticationFilter (验证登录)、JWTAuthorizationFilter (鉴定权限)和UserDetailsServiceImpl类 (查库匹配账号密码)
1.JWTAuthenticationFilter.java (验证登录)
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 (鉴定权限)
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 (查库匹配账号密码)
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); } }
四、FailHandler(账号密码错误时的处理方式)
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")); } }
五、配置SecurityConfig
这个类里规定了权限的相关信息
@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; } }
今天关于《SpringBoot结合JWT怎么实现登录权限控制》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
声明:本文转载于:亿速云 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
最新阅读
更多>
-
405 收藏
-
169 收藏
-
328 收藏
-
270 收藏
-
351 收藏
-
459 收藏
-
133 收藏
-
267 收藏
-
278 收藏
-
236 收藏
-
237 收藏
-
194 收藏
课程推荐
更多>
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习