【三】springboot整合token

互相交流入口地址 

整体目录:

【一】springboot整合swagger

【二】springboot整合自定义swagger

【三】springboot整合token

【四】springboot整合mybatis-plus

【五】springboot整合mybatis-plus

【六】springboot整合redis

【七】springboot整合AOP实现日志操作

【八】springboot整合定时任务

【九】springboot整合redis实现启动服务时热点数据保存在全局和缓存

【十】springboot整合quartz实现定时任务优化

【十一】springboot整合异步调用并获取返回值

【十二】springboot整合WebService

【十三】springboot整合WebService关于传参数

【十四】springboot整合WebSocket

【十五】springboot整合WebSocket实现聊天室

【十六】RabbitMQ基础篇(下载安装并基础使用,内含各种坑问题)

【十七】RabbitMQ基础篇(延迟队列和死信队列实战)

【十八】springboot实现自定义全局异常处理

【十九】初学Kafka并实战整合SpringCloudStream进行使用

【二十】springboot整合ElasticSearch实战(万字篇)

【二十一】springboot整合过滤器实战

【二十二】springboot整合拦截器实战并对比过滤器

【二十三】springboot整合activiti7(1)实战演示篇

【二十四】springboot整合spring事务详解以及实战

【二十五】springboot使用EasyExcel和线程池实现多线程导入Excel数据

【二十六】springboot整合jedis和redisson布隆过滤器处理缓存穿透

【二十七】springboot实现多线程事务处理

【二十八】springboot之threadLocal参数解析器实现session一样保存当前登录功能 

【二十九】springboot整合logback实现日志管理

【三十】springboot项目上高并发解决示例

目录

第一步:新增依赖(在pom文件增加) 

第二步:新增配置类

第三步:新增token工具类(用来生成token以及效验token) 

第四步:改造登陆接口

第五步:演示结果


介绍:接下来我会把学习阶段学到的框架等知识点进行整合,每一次整合是在前一章的基础上进行的,所以后面的整合不会重复放前面的代码。每次的demo我放在结尾,本次是接着上一章的内容延续的,只增加新增的或者修改的代码。

整合token,每次请求接口时进行token效验,效验通过才可以请求到接口,我是通过jwt生成的token。token个人理解大概就是用来判断用户登录状态,是否已登录的。

        首先展示一下目录结构,是根据前面几章进行的增加(原因:内容过多),如下:

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCPeuKZgA==,size_20,color_FFFFFF,t_70,g_se,x_16

第一步:新增依赖(在pom文件增加) 

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </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>

        <!--swagger        -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--swagger-ui.html模式        -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--doc.html模式        -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.9.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.json/json -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20190722</version>
        </dependency>
    </dependencies>

        其实就增加了jwt和json两个依赖。

第二步:新增配置类

TokenInterceptor类(拦截器):
@Component
public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //跨域请求会首先发一个option请求,直接返回正常状态并通过拦截器
        if(request.getMethod().equals("OPTIONS")){
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        response.setCharacterEncoding("utf-8");
        String token = request.getHeader("token");
        if (token!=null){
            boolean result= TokenUtils.verify(token);
            if (result){
                System.out.println("通过拦截器");
                return true;
            }
        }
        response.setContentType("application/json; charset=utf-8");
        try {
            JSONObject json=new JSONObject();
            json.put("msg","token verify fail");
            json.put("code","500");
            response.getWriter().append(json.toString());
            System.out.println("认证失败,未通过拦截器");
        } catch (Exception e) {
            return false;
        }
        /**
         * 还可以在此处检验用户存不存在等操作
         */
        return false;
    }
}
PS:此处token从request里面获取header里面的key值是token,你要根据自己的情况来,你在前端header里面传的token叫什么名称,这里就取什么名字。 
WebConfiguration类(配置拦截器):
@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Autowired
    private TokenInterceptor tokenInterceptor;

    /**
     * 解决跨域请求
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedHeaders("*")
                .allowedMethods("*")
//                .allowedOrigins("*")
                .allowedOriginPatterns("*")
                .allowCredentials(true);
    }

    /**
     * 异步请求配置
     * @param configurer
     */
    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        configurer.setTaskExecutor(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(3)));
        configurer.setDefaultTimeout(30000);
    }

    /**
     * 配置拦截器、拦截路径
     * 每次请求到拦截的路径,就会去执行拦截器中的方法
     * @param configurer
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> excludePath = new ArrayList<>();
        //排除拦截,除了注册登录(此时还没token),其他都拦截
        excludePath.add("/userController/login");  //登录
        excludePath.add("/userController/register");     //注册
        excludePath.add("/doc.html");     //swagger
        excludePath.add("/swagger-ui.html");     //swagger
        excludePath.add("/swagger-resources/**");     //swagger
        excludePath.add("/v2/api-docs");     //swagger
        excludePath.add("/webjars/**");     //swagger
//        excludePath.add("/static/**");  //静态资源
//        excludePath.add("/assets/**");  //静态资源
        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludePath);
        WebMvcConfigurer.super.addInterceptors(registry);

    }
}
PS:addInterceptors方法里面需要按自己情况进行修改,excludePath集合add的是需要放行的接口路径,前几章整合了swagger,所以此处需要放行swagger相关的路径,swagger-ui.html、doc.html、swagger-resources、等等,你再加上自己想要放行的接口路径即可,一般是首页请求的接口以及登录注册的接口(不需要进行token效验的接口)。

第三步:新增token工具类(用来生成token以及效验token) 

public class TokenUtils {

    //token到期时间10小时
    private static final long EXPIRE_TIME= 10*60*60*1000;
    //密钥盐
    private static final String TOKEN_SECRET="ljdyaishijin**3nkjnj??";

    /**
     * 生成token
     * @param user
     * @return
     */
    public static String sign(User user){

        String token=null;
        try {
            Date expireAt=new Date(System.currentTimeMillis()+EXPIRE_TIME);
            token = JWT.create()
                    //发行人
                    .withIssuer("auth0")
                    //存放数据
                    .withClaim("username",user.getUserName())
                    //过期时间
                    .withExpiresAt(expireAt)
                    .sign(Algorithm.HMAC256(TOKEN_SECRET));
        } catch (IllegalArgumentException|JWTCreationException je) {

        }
        return token;
    }


    /**
     * token验证
     * @param token
     * @return
     */
    public static Boolean verify(String token){

        try {
            //创建token验证器
            JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
            DecodedJWT decodedJWT=jwtVerifier.verify(token);
            System.out.println("认证通过:");
            System.out.println("username: " + decodedJWT.getClaim("username").asString());
            System.out.println("过期时间:      " + decodedJWT.getExpiresAt());
        } catch (IllegalArgumentException |JWTVerificationException e) {
            //抛出错误即为验证不通过
            return false;
        }
        return true;
    }

}
PS:此处到期时间可以自定义按情况进行设置,1000是1秒。此处token的生成方法以及效验方法可以根据具体情况进行更改,生成token1是使用的jwt,此处验证方法存在一个用户有多个token的情况(可以同时多次登陆同一账号,重新请求token之后,前一次的token只要没有过期也能使用。),可以整合redis后进行改造(后面会讲到),可以达到一个用户只有一个token的效果(重新请求token之后,前一次的token即使没有过期也不能使用。)

第四步:改造登陆接口

@ApiOperation(value = "登录")
    @GetMapping("/login")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userName", value = "用户名", paramType = "String"),
            @ApiImplicitParam(name = "passWord", value = "密码", paramType = "String")
    })
    public BaseResponse<HashMap> login(@RequestParam(value = "userName") String userName, @RequestParam(value = "passWord") String passWord) throws JsonProcessingException {
        //包装token
        User user = new User();
        user.setUserName(userName);
        user.setPassword(passWord);
        String token= TokenUtils.sign(user);
        HashMap<String,Object> hs=new HashMap<>();
        hs.put("token",token);
        return RespGenerator.returnOK(hs);
    }
PS:可以根据自己的情况包装数据作为登录请求的返回结果。

第五步:演示结果

        1、当请求没有放行的接口不带token请求时: 

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCPeuKZgA==,size_20,color_FFFFFF,t_70,g_se,x_16

        结果:会提示token效验失败。

        2、当请求放行的接口不带token请求时:

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCPeuKZgA==,size_20,color_FFFFFF,t_70,g_se,x_16

        结果:成功请求到接口,此处是登陆接口,返回了token。

        3、当请求没有放行的接口带token请求时: 

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCPeuKZgA==,size_20,color_FFFFFF,t_70,g_se,x_16

         结果:成功请求到接口。

本期整合到此完毕,接下来会继续更新加强整合,尽情期待。

访问地址:http://localhost:8085/swagger-ui.html或者http://localhost:8085/doc.html

  • 72
    点赞
  • 232
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 28
    评论
Spring Boot提供了多种方式来实现Token认证,下面是一种基本的实现方式: 首先,在pom.xml文件中添加Spring Security和JWT依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> ``` 接下来,创建一个JWTUtil类,用于生成和解析Token: ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Date; @Component public class JWTUtil { @Value("${jwt.secret}") private String secret; @Value("${jwt.expiration}") private Long expiration; public String generateToken(String username) { Date now = new Date(); Date expireDate = new Date(now.getTime() + expiration * 1000); return Jwts.builder() .setSubject(username) .setIssuedAt(now) .setExpiration(expireDate) .signWith(SignatureAlgorithm.HS512, secret) .compact(); } public String getUsernameFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } public boolean validateToken(String token, String username) { String tokenUsername = getUsernameFromToken(token); return tokenUsername.equals(username) && !isTokenExpired(token); } private boolean isTokenExpired(String token) { Date expirationDate = Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody() .getExpiration(); return expirationDate.before(new Date()); } } ``` 然后,创建一个JwtAuthenticationFilter类,用于处理Token认证: ```java 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.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter { private final JWTUtil jwtUtil; public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JWTUtil jwtUtil) { super(new AntPathRequestMatcher("/api/login", "POST")); setAuthenticationManager(authenticationManager); this.jwtUtil = jwtUtil; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { String username = request.getParameter("username"); String password = request.getParameter("password"); return getAuthenticationManager().authenticate( new UsernamePasswordAuthenticationToken(username, password) ); } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { String username = ((UserDetails) authResult.getPrincipal()).getUsername(); String token = jwtUtil.generateToken(username); response.addHeader("Authorization", "Bearer " + token); } } ``` 最后,在SecurityConfig中配置认证: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { private final UserDetailsService userDetailsService; private final PasswordEncoder passwordEncoder; private final JWTUtil jwtUtil; @Autowired public SecurityConfig(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder, JWTUtil jwtUtil) { this.userDetailsService = userDetailsService; this.passwordEncoder = passwordEncoder; this.jwtUtil = jwtUtil; } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/login").permitAll() .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager(), jwtUtil)); } @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } } ``` 以上即为使用Spring Boot整合Token认证的基本步骤。首先,在JWTUtil类中实现Token的生成和解析逻辑,然后通过JwtAuthenticationFilter处理请求中的Token,最后在SecurityConfig中配置认证规则。
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小z♂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值