• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

SpringBoot集成Spring security JWT实现接口权限认证

springboot 搞代码 4年前 (2022-01-05) 40次浏览 已收录 0个评论
文章目录[隐藏]

这篇文章主要介绍了SpringBoot集成Spring security JWT实现接口权限认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1、添加依赖

  org.springframework.bootspring-boot-starter-security io.jsonwebtokenjjwt0.9.1

2、集成JWT工具类(JwtUtils)

 package com.dreamteam.chdapp.utils; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * @Author HeYunHui * @create 2020/11/15 14:12 */ public class JwtUtils { private static final Logger logger= LoggerFactory.getLogger(JwtUtils.class); public static  final long EXPIRATION_TIME=60*60*1000;// 令牌环有效期 public static final String SECRET="abc123456def";//令牌环密钥 public static final String TOKEN_PREFIX="Bearer";//令牌环头标识 public static final String HEADER_STRING="Passport";//配置令牌环在http heads中的键值 public static final String ROLE="ROLE";//自定义字段-角色字段 //生成令牌环 public static String generateToken(String userRole,String userid){ HashMap map=new HashMap(); map.put(ROLE,userRole); map.put("userid",userid); String jwt= Jwts.builder() .setClaims(map) .setExpiration(new Date(System.currentTimeMillis()+EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512,SECRET) .compact(); return TOKEN_PREFIX+" "+jwt; } //生成令牌环 public static String generateToken(String userRole,String userid,long exprationtime){ HashMap map=new HashMap(); map.put(ROLE,userRole); map.put("userid",userid); String jwt= Jwts.builder() .setClaims(map) .setExpiration(new Date(System.currentTimeMillis()+exprationtime)) .signWith(SignatureAlgorithm.HS512,SECRET) .compact(); return TOKEN_PREFIX+" "+jwt; } //令牌环校验 public static Map validateTokenAndGetClaims(HttpServletRequest request){ String token=request.getHeader(HEADER_STRING); if(token==null){ throw new TokenValidationException("Missing Token"); } else{ Map body= Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token.replace(TOKEN_PREFIX,"")) .getBody(); return body; } } static class TokenValidationException extends RuntimeException{ public TokenValidationException(String msg){ super(msg); } } }

3、集成JWT filter(拦截器/过滤器)

 package com.dreamteam.chdapp.filter; import com.dreamteam.chdapp.utils.JwtUtils; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import org.springframework.web.filter.OncePerRequestFilter; 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.Arrays; import java.util.Map; import static com.dreamteam.chdapp.utils.JwtUtils.ROLE; /** * @Author HeYunHui * @create 2020/11/15 14:46 */ public class JwtAuthenticationFilter extends OncePerRequestFilter { private static final PathMatcher pathmatcher = new AntPathMatcher(); private String[] protectUrlPattern = {"/manage/**", "/member/**", "/auth/**"}; //哪  些请求需要进行安全校验 public JwtAuthenticationFilter() { } @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { //是不是可以在这里做多种方式登录呢 try { if (isProtectedUrl(httpServletRequest)) { Map claims = JwtUtils.validateTokenAndGetClaims(httpServletRequest); String role = String.valueOf(claims.get(ROLE)); String userid = String.valueOf(claims.get("userid")); //最关键的部分就是这里, 我们直接注入了 SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken( userid, null, Arrays.asList(() -> role) )); } } catch (Exception e) { e.printStackTrace(); httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); return; } filterChain.doFilter(httpServletRequest, httpServletResponse); } //是否是保护连接 private boolean isProtectedUrl(HttpServletRequest request) { boolean flag = false; for (int i = 0; i <protectUrlP<div style="color:transparent">来源gaodai.ma#com搞##代!^码@网</div>attern.length; i++) { if (pathmatcher.match(protectUrlPattern[i], request.getServletPath())) { return true; } } return false; } } 

4、配置JWT config类(配置类)

跨域访问:客户端与服务端域名不同或是端口号不同。防止跨域攻击

 package edu.ynmd.cms.config; import edu.ynmd.cms.filter.JwtAuthenticationFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; 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.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.StrictHttpFirewall; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } @Bean public HttpFirewall allowUrlEncodedSlashHttpFirewall() { StrictHttpFirewall firewall = new StrictHttpFirewall(); firewall.setAllowUrlEncodedSlash(true); return firewall; } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .cors()  //允许跨域访问 .and() .authorizeRequests() .antMatchers("/").authenticated() //配置那些url需要进行校验--所有请求都需要校验"/" .antMatchers("/public/**").permitAll() //那些请求不需要校验 .anyRequest().authenticated() //自定义校验类 .and() .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS)//关闭session ; } } 

5、Action注解

在Controller类中添加

 @CrossOrigin @RestController @PreAuthorize("hasAuthority('admin')") //配置角色,拥有该角色的用户方可访问 @RequestMapping("/manage") 

postman测试http://localhost:7070/manage/userList,不可访问

public开头的可以访问

6、token令牌环,访问需校验的资源

public的Controller类添加

 @PostMapping("/login") @ResponseBody public HashMap login( @RequestBody Account account) throws IOException { //        Users u=manageService.getUserByUserNameAndPass(account.username,account.password); if(account.username.equals("admin")&&account.password.equals("123456")){ //        if(u!=null){ String jwt= JwtUtils.generateToken("admin","123456789abc"); //            String jwt= JwtUtils.generateToken(u.getRoleid(),u.getUsersid()); return new HashMap(){{ put("msg","ok"); put("token",jwt); //                put("role",u.getRoleid()); put("role","admin"); }}; } else { //return new ResponseEntity(HttpStatus.UNAUTHORIZED); return new HashMap(){{ put("msg","error"); put("token","error"); }}; } } public static class Account{ public String username; public String password; } 

postman测试,随便输用户名密码

输入代码中的用户名密码

去JWT官网https://jwt.io/,页面下滑,将得到的token输入,得到

manage的Controller类中添加测试

 @GetMapping("testSecurityResource") @ResponseBody public String testSecurityResource() throws Exception{ return "受保护的资源"; } 

用postman访问http://localhost:7070/manage/testSecurityResource,返回结果

7、service工具类

通用请求处理

 package com.dreamteam.chdapp.controller.common; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; /** * 通用请求处理 * @Author HeYunHui * @create 2020/11/14 15:38 */ @Controller public class CommonController { protected static final Logger log= LoggerFactory.getLogger(CommonController.class); /** * 字符串为空 * @param value * @return */ public static boolean isNullOrSpace(String value){ if(value==null){ return true; } else { if(value.equals("")){ return true; } else { return false; } } } } 

Service层

 String getCurrentUserId();//从令牌环中获取userid String getCurrentRole();//从令牌环中获取角色id 

ServiceImpl

 /** * 获取当前登录用的的Id * @return */ @Override public String getCurrentUserId() { String userid= (String) SecurityContextHolder.getContext().getAuthentication() .getPrincipal(); if(CommonController.isNullOrSpace(userid)){ return null; } else { return userid; } } /** * 获取当前登录用户的角色 * @return */ @Override public String getCurrentRole() { String role=null; Collection authorities = (Collection)    SecurityContextHolder.getContext().getAuthentication().getAuthorities(); for (GrantedAuthority authority : authorities) { role = authority.getAuthority(); } if(CommonController.isNullOrSpace(role)){ return null; } else{ return role; } } 

修改manage的Controller类

 @GetMapping("testSecurityResource") @ResponseBody public String testSecurityResource() throws Exception{ String userid=userInfoService.getCurrentUserId(); String role=userInfoService.getCurrentRole(); return "受保护的资源,当前用户的id是"+userid+"当前用户的角色是"+role; } 

用postman测试

这是前面自定义的

8、识别token信息

如果将下图中的角色换掉,将不能访问

9、自动更新令牌环

添加Controller类

 package com.dreamteam.chdapp.controller; import com.dreamteam.chdapp.controller.common.CommonController; import com.dreamteam.chdapp.utils.JwtUtils; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.Collection; import java.util.HashMap; /** * 令牌环自动更新 * @Author HeYunHui * @create 2020/11/16 17:24 * @PreAuthorize("hasAuthority('admin')")//只允许有admin角色的用户访问 hasAnyAuthority([auth1,auth2]) */ @CrossOrigin @RestController @PreAuthorize("hasAnyAuthority('admin','member')") @RequestMapping("/auth") public class AuthController { /** * 更新令牌环信息 * @param request * @return */ @GetMapping("refreshToken") @ResponseBody public HashMap refreshToken(HttpServletRequest request){ String role=null; Collection authorities = (Collection)    SecurityContextHolder.getContext().getAuthentication().getAuthorities(); for (GrantedAuthority authority : authorities) { role = authority.getAuthority(); } // UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication() .getPrincipal(); String userid= (String)SecurityContextHolder.getContext().getAuthentication() .getPrincipal(); if(CommonController.isNullOrSpace(role)){ return new HashMap(){{ put("token","error"); }}; } else{ String jwt=""; //一小时 jwt= JwtUtils.generateToken(role,userid,60*60*1000); HashMap m=new HashMap(); m.put("token",jwt); return m; } } /** * 获取当前登录用户的角色 * @return */ @GetMapping("getRole") @ResponseBody public HashMap getRoleByToken(){ String role=""; String userid=""; Collection authorities = (Collection)    SecurityContextHolder.getContext().getAuthentication().getAuthorities(); for (GrantedAuthority authority : authorities) { role = authority.getAuthority(); } if(CommonController.isNullOrSpace(role)){ return new HashMap(){{ put("role","error"); }}; } else{ HashMap m=new HashMap(); m.put("role",role); return m; } } } 

用postman测试

10、使用数据库存储用户信息

(1)实体类

 package com.dreamteam.chdapp.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.stereotype.Component; @Component @Data @AllArgsConstructor @NoArgsConstructor /** * 表名 */ @TableName("users") public class Users { @TableId(type = IdType.AUTO) private String usrId; private String usrName; private String usrTel; private String usrPwd; private String usrType; } 

UserMapper

 package com.dreamteam.chdapp.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dreamteam.chdapp.entity.Users; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; import java.util.List; /** * @Author HeYunHui * @create 2020/11/11 21:50 */ @Repository @Mapper public interface UserMapper extends BaseMapper { List getUsersByUsrNameAndPwd(@Param("usrName")String usrName, @Param("usrPwd") String usrPwd); } 

UsersMapper.xml

    select * from users where #{usrName}=usr_name and #{usrPwd}=usr_pwd 

service

 Users getUsersByUsrNameAndPwd(String usrName,String usrPwd); 

serviceImpl JWT获取用户名密码

 @Override public Users getUsersByUsrNameAndPwd(String usrName, String usrPwd) { List ul=userMapper.getUsersByUsrNameAndPwd(usrName,usrPwd); if(ul.size()>0){ return ul.get(0); } return null; } 

Controller

 @PostMapping("/login") @ResponseBody public HashMap login( @RequestBody Account account) throws IOException { Users u=userInfoService.getUsersByUsrNameAndPwd(account.username,account.password); //        if(account.username.equals("admin")&&account.password.equals("123456")){ if(u!=null){ //            String jwt= JwtUtils.generateToken("admin","123456789abc"); String jwt= JwtUtils.generateToken(u.getUsrType(),u.getUsrId()); return new HashMap(){{ put("msg","ok"); put("token",jwt); put("role",u.getUsrType()); //                put("role","admin"); }}; } else { //return new ResponseEntity(HttpStatus.UNAUTHORIZED); return new HashMap(){{ put("msg","error"); put("token","error"); }}; } } public static class Account{ public String username; public String password; } 

postman测试

a.登录,生成token

b.输入token访问manage下的链接

以上就是SpringBoot集成Spring security JWT实现接口权限认证的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:SpringBoot集成Spring security JWT实现接口权限认证

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址