springboot整合security(三)

前两天讲解了简单的整合和数据库登录

一:https://blog.csdn.net/weixin_45948218/article/details/118158861?spm=1001.2014.3001.5501

二:https://blog.csdn.net/weixin_45948218/article/details/118161787?spm=1001.2014.3001.5501

 今天整合jwt进行token检验,今天在(二)的基础上新增了一些包

 直接上代码

UsersController

package com.example.security02.controller;

import com.example.security02.entity.Users;
import com.example.security02.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class UsersController {
    @Autowired
    UsersService us;

    @GetMapping
    public Users query(String uname){
        return us.query(uname);
    }

}
JwtUtils
package com.example.security02.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Map;

public class JwtUtils {
    private static final String SECRET ="123456";


    /**
     * 创建token
     * @param user
     * @param role
     * @return
     */
    public static String createToken(String user,String role){
        LocalDateTime plus = LocalDateTime.now().plus(60, ChronoUnit.SECONDS);//设置token过期时间,单位秒,可修改
        Instant instant = plus.atZone(ZoneId.systemDefault()).toInstant();
        Date from = Date.from(instant);

        return JWT.create().withSubject(user)
                .withClaim("user",user)//用户信息
                .withClaim("role",role)//角色信息
                .withExpiresAt(from)
                .sign(Algorithm.HMAC384(SECRET));//加密方式HMAC384
    }


    /**
     * 校验token
     * @param token
     * @return
     */
    public static Map<String, Claim> check(String token){//校验token
        JWTVerifier verifier = JWT.require(Algorithm.HMAC384(SECRET)).build();
        return verifier.verify(token).getClaims();
    }
}
Results
package com.example.security02.utils;

import java.util.HashMap;

public class Results  extends HashMap<String,Object> {


    private static final long serialVersionUID = 4718239289210979368L;

    public static Results resp(Integer status, String mes, Object data){//可自定义
        Results res = new Results();
        res.put("status",status);//状态码
        res.put("message",mes);//消息
        res.put("data",data);//数据
        return res;
    }




}
SecurityConfig
package com.example.security02.config;

import com.auth0.jwt.interfaces.Claim;
import com.example.security02.utils.JwtUtils;
import com.example.security02.utils.Results;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        super.configure(http);
          http.authorizeRequests().antMatchers("/systemUser/add").permitAll();//systemUser/add这个api不需要登录就可以访问,多个用,分隔

        //自定义过滤器    在UsernamePasswordAuthenticationFilter之前执行
        http.addFilterBefore((req,resp,auth)->{
            HttpServletRequest re=(HttpServletRequest)req;//获取request
            String token=re.getHeader("token");//获取请求头中的token
            try {
                if(!ObjectUtils.isEmpty(token)){
                    //如果不抛出异常,就表示校验通过
                    Map<String, Claim> check = JwtUtils.check(token);//调用校验方法
                    String user=check.get("user").asString();
                    String role=check.get("role").asString();
                    List<GrantedAuthority> grantedAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(role);
                    //封装auth
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user, null, grantedAuthorities);
                    //存入securitycontextholder
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                }
            }catch (Exception e){
                e.printStackTrace();
                Results ok = Results.resp(500, "出错啦!", e.getMessage());
                resp.setContentType("application/json;charset=utf-8");
                ObjectMapper mapper=new ObjectMapper();
                mapper.writeValue(resp.getWriter(),ok);
            }
            auth.doFilter(req,resp);
        }, UsernamePasswordAuthenticationFilter.class);

        //关闭默认的session机制
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        //请求没有权限时的异常处理
        http.exceptionHandling().authenticationEntryPoint((req,resp,auth)->{
            Results ok = Results.resp(403, "请先登录!", "");
            resp.setContentType("application/json;charset=utf-8");
            ObjectMapper mapper=new ObjectMapper();
            mapper.writeValue(resp.getWriter(),ok);
        });

        http.csrf().disable();
        http.formLogin().usernameParameter("user").passwordParameter("pass")
                .loginProcessingUrl("/login")
                .successHandler((req,resp,auth)->{//成功回调
                    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                    User principal = (User) authentication.getPrincipal();
                    Collection<GrantedAuthority> authorities = principal.getAuthorities();
                    String s = StringUtils.collectionToCommaDelimitedString(authorities);
                    String token = JwtUtils.createToken(principal.getUsername(), s);//调用token创建方法

                    Results ok = Results.resp(200, "ok", token);//返回token
                    resp.setContentType("application/json;charset=utf-8");
                    ObjectMapper mapper=new ObjectMapper();
                    mapper.writeValue(resp.getWriter(),ok);
                })
                .failureHandler((req,resp,auth)->{//失败回调
                    Results ok = Results.resp(500, "error", "");
                    resp.setContentType("application/json;charset=utf-8");
                    ObjectMapper mapper=new ObjectMapper();
                    mapper.writeValue(resp.getWriter(),ok);
                })
                .permitAll();
        http.authorizeRequests().anyRequest().authenticated();
    }
}

如果需要跨域代码做如下修改:将最后一行的:

http.authorizeRequests().anyRequest().authenticated();

修改为:

http.authorizeRequests().anyRequest().authenticated().and().cors().and().headers().frameOptions().disable();

并创建CorsConfigurationSource对象放入容器,直接加在SecurityConfig里即可

@Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.addAllowedHeader("*");
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

完成!打开postman测试一下

token过期也会返回相应信息,以此来做前端的判断.

整合jwt到这就完成啦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

心心丶念念

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

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

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

打赏作者

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

抵扣说明:

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

余额充值