springboot使用security+token认证完成注册登录和权限管理

security实现加密和匹配密码

导入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

引入依赖后会默认拦截所有路径的请求,可新建一个配置类进行配置,下面的配置适用于仅使用security的加密功能

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //authorizeRequests所有security全注解配置实现的开端,表示开始说明需要的权限。
        //需要的权限分两部分,第一部分是拦截的路径,第二部分访问该路径需要的权限。
        //antMatchers表示拦截什么路径,permitAll任何权限都可以访问,直接放行所有。
        //anyRequest()任何的请求,authenticated认证后才能访问
        //.and().csrf().disable();固定写法,表示使csrf拦截失效。
        //此配置适用于仅使用security的加密,不使用它的拦截功能
        http
                .authorizeRequests()
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated()
                .and().csrf().disable();
    }
}

在启动类里注入bean

    @Bean
    public BCryptPasswordEncoder encoder(){
        return new BCryptPasswordEncoder();
    }

在service层注入

    @Autowired
    private BCryptPasswordEncoder encoder;

密码加密,此代码为示例,参数是未加密的password

user.setPassword(encoder.encode(password));

匹配密码,第一个参数是用户输入的密码,第二个是加密的密码,匹配成功返回true,失败false

encoder.matches(password,user.getPassword())

jwt和token认证

引入依赖

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
        </dependency>

在启动类中注入

	@Bean
	@ConfigurationProperties("jwt.config")
	public JwtUtil jwtUtil(){
		return new JwtUtil();
	}

创建jwt工具类

public class JwtUtil {

    private String key ;

    private long ttl ;//一个小时

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public long getTtl() {
        return ttl;
    }

    public void setTtl(long ttl) {
        this.ttl = ttl;
    }

    /**
     * 生成JWT
     *
     * @param id
     * @param subject
     * @return
     */
    public String createJWT(String id, String subject, String roles) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        JwtBuilder builder = Jwts.builder().setId(id)
                .setSubject(subject)
                .setIssuedAt(now)
                .signWith(SignatureAlgorithm.HS256, key).claim("roles", roles);
        if (ttl > 0) {
            builder.setExpiration( new Date( nowMillis + ttl));
        }
        return builder.compact();
    }

    /**
     * 解析JWT
     * @param jwtStr
     * @return
     */
    public Claims parseJWT(String jwtStr){
        return  Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(jwtStr)
                .getBody();
    }

}

在配置文件中配置盐和过期时间

jwt:
  config:
    key: itcast
    ttl: 3600000

登录成功后生成token

		String token = jwtUtil.createJWT(adminLogin.getId(), adminLogin.getLoginname(), "admin");
		Map<String,Object> map =new HashMap<>();
		map.put("token",token);
		map.put("role","admin");

创建一个拦截器,拦截器只是负责把有请求头中包含token的令牌进行一个解析验证

@Component
public class JwtInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtUtil jwtUtil;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("经过了拦截器");
        //无论如何都放行。具体能不能操作还是在具体的操作中去判断。
        //拦截器只是负责把有请求头中包含token的令牌进行一个解析验证。
        String header = request.getHeader("Authorization");

        if(header!=null && !"".equals(header)){
            //如果有包含有Authorization头信息,就对其进行解析
            if(header.startsWith("Bearer ")){
                //得到token
                String token = header.substring(7);
                //对令牌进行验证
                try {
                    Claims claims = jwtUtil.parseJWT(token);
                    String roles = (String) claims.get("roles");
                    if(roles!=null && roles.equals("admin")){
                        request.setAttribute("claims_admin", token);
                    }
                    if(roles!=null && roles.equals("user")){
                        request.setAttribute("claims_user", token);
                    }
                }catch (Exception e){
                    throw new RuntimeException("令牌不正确!");
                }
            }
        }
        return true;
    }
}

配置拦截器

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {

    @Autowired
    private JwtInterceptor jwtInterceptor;
    protected void addInterceptors(InterceptorRegistry registry) {
        //注册拦截器要声明拦截器对象和要拦截的请求
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/**/login/**");
}
}

在需要登录权限的地方获取token

		String token = (String) request.getAttribute("claims_admin");
		if(token == null || "".equals(token)){
			throw new RuntimeException("权限不足!");
		}
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值