密码加密与微服务鉴权JWT

1. BCrypt密码加密

密码应该通过哈希算法进行加密,有很多标准算法如SHA或者MD5,结合salt(盐)是一个不错的选择。Spring Security提供了BCryptPasswordEncoder类,实现Spring的PasswordEncoder接口使用BCrypt强哈希方法来加密密码。BCrypt强哈希方法每次加密结果都不一样。

导包

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

配置

// 安全配置类
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    // authorizeRequests所有security全注解配置实现的开端,表示开始说明需要的权限
    // 需要的权限分两部分,第一部分时拦截的路径,第二部分是访问该路径需要的权限
    // anyMatches表示拦截什么路径,permitAll任何路径都可以访问
    // anyRequest任何的请求,authenticated认证后才能访问
    // and().csrf().disable(),固定写法,表示csrf拦截失效
    @Overide
    protected void configure(HttpSecurity http) throws Exception{
            http.authorizeRequests()
                .anyMatches("/**").permitAll()
                .anyRequest().authenticated()
                .and().csrf().disable();
    }

}

使用

// 启动类注入BCryptPasswordEncoder
@Bean
public BCryptPasswordEncoder(){
    return new BCryptPasswordEncoder();
}

// 注入后直接调用即可
@Autowired
private BCryptPasswordEncoder encoder;

// 加密
encoder.encode("password");
// 密码比较
encoder.matches("用户输入密码", "数据库密码");

2. 常见的认证机制

2.1 HTTP Basic Auth

2.2 Cookie Auth

Cookie认证机制就是为一次请求认证在服务端创建一个Session对象,同时在客户端浏览器创建了一个Cookie对象;通过客户端带上来的Cookie对象与服务器端的session对象匹配来实现状态管理的。默认的,当我们关闭浏览器的时候,cookie会被删除。但可以通过cookie的expire time使cookie在一定时间内有效。

2.3 OAuth

2.4 Token Auth

使用基于Token的身份验证方法,在服务端不需要存储用户的登录记录,流程如下:
1)客户端使用用户名和密码请求登录
2)服务端收到请求,去验证用户名与密码
3)验证成功后,服务端会签发一个Token,再把这个Token发给客户端
4)客户端收到Token后把它存储起来,比如放在Cookie里
5)客户端每次请求服务端资源时都需要带着服务端签发的Token
6)服务端收到请求,然后去验证客户端请求里面带着的Token,如果验证成功就向客户端返回请求的数据】

Token机制优点:
1)支持跨域访问:Cookie不允许跨域访问
2)无状态:Token机制在服务端不需要存储session信息
3)更适用CDN
4)去耦
5)更适用于移动应用
6)CSRF,因为不再依赖Cookie,所以不需要考虑对CSRF(跨站请求伪造)的防范
 

3. 基于JWT的Token认证机制

JSON Web Token是一个非常轻巧的规范,这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。

一个JWT实际上就是一个字符串,由三部分组成——头部(Header)、载荷(playload)与签证(signature)。

头部:用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法,如{"type": "JWT", "alg": "HS256"}
载荷:存放有效信息的地方,如 {"sub": "1234567890", "name": "Tom"}
签证:由三部分组成header(base64为后的),playload(base64位后的),secret(盐)

注意:secret是保存在服务端的,jwt的签发生成也是在服务端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,任何时候不应流露出来。

 

4. Java的JJWT实现JWT

JJWT是一个提供端到端的JWT创建和验证的Java库。

导包

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

使用

// 生成JWT 设置过期时间,自定义属性等
JwtBuilder jwtBuilder = Jwts.builder()
        .setId("1")
        .setSubject("Tom")
        .setIssuedAt(new Date())
        .signWith(SignatureAlgorithm.JS256, "salt")
        .setExpiration(new Date(new Date().getTime() + 60 * 1000))
        .claims("role", "admin");
System.out.println(jwtBuilder.compact());

// 解析JWT
Claims claims = JWTs.parser().setSigningKey("salt")
        .parseClaimsJws("加密后的Token")
        .getBody();
System.out.println("用户名id:" + claims.getId());

5. 拦截器实现用户权限控制

拦截器

@Component
public class JwtInterceptor implements HandlerInterceptor{
    
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throw Exception{
        System.out.println("经过了拦截器");
        // 无论如何都放行,具体能不能操作还是在具体的操作中去判断
        // 拦截器只是负责把请求头中包含token的令牌进行一个解析验证
        String header = request.getHeader("Authorization"); // Authorization这个是前后端约定好的需要添加头信息,token放请求头更安全
        if(header != null && !"".equals(header)){
            String token = header;
            try{
                Claims claim = jwtUtil.parseJWT(token);
                String roles = (String)claim.get("roles");
                if(roles != null && roles .equals("admin")){
                    request.setAttribute("claims_admin", token);
                }
            }catch(Exception e){
                throw new RuntimeException("权限不足!");
            }
        }
        return true;
    }

}

拦截配置

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport{

    @Autowired
    private JwtInterceptor jwtInterceptor;

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

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值