SpringBoot+JWT实现用户接口访问权限验证

流程:

1.用户访问login接口,验证用户身份信息,并生成token绑定用户信息,token返回前端

2.前端把token存入request header中访问后端接口即可成功,否则提示无权访问

代码部分:

1.JwtUtil类 (生成token,校验token等)

/* *
 * @Author qy
 * <p> JWT工具类 </p>
 * @Param
 * @Return
 */
public class JwtUtil {

    // Token过期时间30分钟
    public static final long EXPIRE_TIME = 30 * 60 * 1000;

    /* *
     * @Author qy
     * <p> 校验token是否正确 </p>
     * @Param token
     * @Param username
     * @Param secret
     * @Return boolean
     */
    public static boolean verify(String token, String username, String secret) {
        try {
            // 设置加密算法
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim("username", username)
                    .build();
            // 效验TOKEN
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception exception) {
            return false;
        }
    }

    /* *
     * @Author qy
     * <p>生成签名,30min后过期 </p>
     * @Param [username, secret]
     * @Return java.lang.String
     */
    public static String sign(String username, String secret) {
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        Algorithm algorithm = Algorithm.HMAC256(secret);
        // 附带username信息
        return JWT.create()
                .withClaim("username", username)
                .withExpiresAt(date)
                .sign(algorithm);

    }

    /* *
     * @Author qy
     * <p> 获得用户名 </p>
     * @Param [request]
     * @Return java.lang.String
     */
    public static String getUserNameByToken(HttpServletRequest request) {
        String token = request.getHeader("token");
        DecodedJWT jwt = JWT.decode(token);
        return jwt.getClaim("username")
                .asString();
    }
}

2.JwtInterceptor (拦截请求类,校验错误返回错误信息)

/**
 * @Author qinyi
 * <p>token验证拦截器 </p>
 */
@Component
public class JwtInterceptor implements HandlerInterceptor {
    @Autowired
    SysUserService sysUserService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从 http 请求头中取出 token
        String token = request.getHeader("token");
        // 如果不是映射到方法直接通过
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
        if (token != null){
            String username = JwtUtil.getUserNameByToken(request);
            // 这边拿到的 用户名 应该去数据库查询获得密码,简略,步骤在service直接获取密码
            boolean result = JwtUtil.verify(token,username,sysUserService.getPassword(username));
            if(result){
                System.out.println("通过拦截器");
                return true;
            }
        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter out = null ;
        try {
            JSONObject res = new JSONObject();
            res.put("success", "false");
            res.put("msg", "您无权访问");
            out = response.getWriter();
            out.append(res.toString());
        }catch (Exception e){
            e.printStackTrace();
            response.sendError(500);
        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

3. InterceptorConfig (拦截器配置类注入spring管理,配置只放通login,拦截其他所有请求,并支持跨域)

/* *
 * @Author qy
 * <p>拦截器配置 </p>
 * @Param
 * @Return
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    /* *
     * @Author qy
     * <p> 设置拦截路径 </p>
     * @Param [registry]
     * @Return void
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/sysuser/login");
    }
    /* *
     * @Author qy
     * <p> 将拦截器注入context </p>
     * @Param []
     * @Return com.zszxz.jwt.interceptor.JwtInterceptor
     */
    @Bean
    public JwtInterceptor authenticationInterceptor() {
        return new JwtInterceptor();
    }

    /* *
     * @Author qy
     * <p>跨域支持 </p>
     * @Param [registry]
     * @Return void
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD")
                .maxAge(3600 * 24);
    }
}

4.controller层示例


/**
 * @author qinyi
 * @since 2021-07-22 10:40:42
 */
@CrossOrigin
@RestController
@RequestMapping("sysuser")
public class LoginController {
    /**
     * 服务对象
     */
    @Resource
    private SysUserService sysUserService;



    @PostMapping("login")
    public ResponseData queryPaper(HttpServletRequest request,@RequestBody SysUser sysUser){
        ResponseData res = ResponseData.ok();
        String username = sysUser.getUserName();
        String password = sysUser.getPassword();
        //账号密码验证
        String token = JwtUtil.sign(username,password);
        if(null != token){
            res.putDataValue("token",token);
        }else {
            res = ResponseData.unauthorized();
        }
        return res;
    }

}

5.pom.xml引入

        <!-- 引入jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.8.2</version>
        </dependency>

6.postman访问成功结果

 token过期或错误-失败结果

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Spring Boot是一个基于Spring框架的快速开发Web应用程序的框架,Spring Security是Spring框架的安全模块,JWT是一种用于身份验证的开放标准。Vue是一种流行的JavaScript框架,用于构建用户界面。 结合这些技术,可以实现前后端分离的登录、权限管理和Token管理。具体步骤如下: 1. 在Spring Boot项目中导入Spring Security和JWT的Maven依赖。 2. 配置Spring Security,包括创建用户、角色和权限等。 3. 创建一个JWT工具类,用于生成和解析Token。 4. 创建一个登录接口,接收用户名和密码,验证用户信息,生成Token并返回给前端。 5. 创建一个Token验证过滤器,用于验证请求中的Token是否有效。 6. 在Vue项目中使用Axios发送登录请求,获取Token并保存到本地存储中。 7. 在Vue项目中使用Vue Router和VueX进行路由和状态管理。 8. 创建一个路由守卫,用于验证用户是否登录和是否有权限访问某些页面。 9. 在需要进行身份验证的请求中添加Token。 下面是一个简单的示例代码,仅供参考: 后端代码: ```java // 配置Spring Security @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public JwtAuthenticationFilter jwtAuthenticationFilter() { return new JwtAuthenticationFilter(); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/auth/**").permitAll() .anyRequest().authenticated() .and() .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint) .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); } } // 创建一个JWT工具类 public class JwtUtils { private static final String SECRET_KEY = "mySecretKey"; private static final long EXPIRATION_TIME = 86400000; // 24 hours public static String generateToken(UserDetails userDetails) { Map<String, Object> claims = new HashMap<>(); return Jwts.builder() .setClaims(claims) .setSubject(userDetails.getUsername()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact(); } public static String getUsernameFromToken(String token) { return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject(); } public static boolean validateToken(String token, UserDetails userDetails) { String username = getUsernameFromToken(token); return username.equals(userDetails.getUsername()) && !isTokenExpired(token); } private static boolean isTokenExpired(String token) { Date expiration = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getExpiration(); return expiration.before(new Date()); } } // 创建一个登录接口 @RestController @RequestMapping("/api/auth") public class AuthController { @Autowired private AuthenticationManager authenticationManager; @Autowired private UserDetailsService userDetailsService; @PostMapping("/login") public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); SecurityContextHolder.getContext().setAuthentication(authentication); UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername()); String token = JwtUtils.generateToken(userDetails); return ResponseEntity.ok(new JwtAuthenticationResponse(token)); } } // 创建一个Token验证过滤器 public class JwtAuthenticationFilter extends OncePerRequestFilter { @Autowired private UserDetailsService userDetailsService; @Autowired private JwtUtils jwtUtils; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String header = request.getHeader("Authorization"); if (header != null && header.startsWith("Bearer ")) { String token = header.substring(7); String username = jwtUtils.getUsernameFromToken(token); UserDetails userDetails = userDetailsService.loadUserByUsername(username); if (jwtUtils.validateToken(token, userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); } } filterChain.doFilter(request, response); } } // 创建一个自定义的AuthenticationEntryPoint @Component public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); } } // 创建一个自定义的UserDetailsService @Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found with username: " + username); } return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>()); } } // 创建一个实体类User和一个接口UserRepository @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "username") private String username; @Column(name = "password") private String password; // getters and setters } @Repository public interface UserRepository extends JpaRepository<User, Long> { User findByUsername(String username); } ``` 前端代码: ```javascript // 在Vue项目中使用Axios发送登录请求 axios.post('/api/auth/login', { username: 'admin', password: 'password' }).then(response => { localStorage.setItem('token', response.data.token); }); // 在需要进行身份验证的请求中添加Token axios.get('/api/users', { headers: { Authorization: 'Bearer ' + localStorage.getItem('token') } }); // 创建一个路由守卫 router.beforeEach((to, from, next) => { const publicPages = ['/login', '/register']; const authRequired = !publicPages.includes(to.path); const loggedIn = localStorage.getItem('token'); if (authRequired && !loggedIn) { return next('/login'); } next(); }); // 使用VueX进行状态管理 const store = new Vuex.Store({ state: { isLoggedIn: !!localStorage.getItem('token') }, mutations: { login(state) { state.isLoggedIn = true; }, logout(state) { state.isLoggedIn = false; } }, actions: { login({ commit }) { return new Promise(resolve => { axios.post('/api/auth/login', { username: 'admin', password: 'password' }).then(response => { localStorage.setItem('token', response.data.token); commit('login'); resolve(); }); }); }, logout({ commit }) { return new Promise(resolve => { localStorage.removeItem('token'); commit('logout'); resolve(); }); } } }); ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值