在Spring boot项目中使用Bcrypt加密,使用JJWT实现创建token!

*

@Autowired
private Environment env;//拿到所有配置文件里的所有属性,k,v类型

//怎么获取值呢

String accessKeyId =env.getProperty("accessKeyId");

1.引入Bcrypt工具类,这个类里有。

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

这个包只要你开始引入那么整个项目特么多是不能访问的!

有什么办法呢?放开拦截就解决这个问题了!因为我们使用这个类也是因为这个jar包特么的拥有Bcrypt工具类!

怎么放开呢?

创建下面这个类必须是跟Spring boot启动文件放在一级!

@Configuration   //告诉项目这是个配置文件早点加载
@EnableWebSecurity //以实现Web安全性
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{//基类是个牛逼的类包含了很多涉及安全要使用的方法比如下面个重写的方法!

//下面这个方法简单的可以理解放开所有拦截!详细自己查!
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
}

2.在Spring boot项目中的

扫描二维码关注公众号,回复: 5495124 查看本文章
Application启动类中添加一个加密工具类。如下

@Bean

prublic BcryptPasswordEncoder encoder(){

return new BcryptPasswordEncoder();

}

上面这个方法主要就是编写这个工具类加载到项目的容器中,那么加密的工具类算是解决了!

下面简单的操作下怎么使用这个类来实现用户密码的加密和登录时候的验证!

@Autowired

private BcryptPasswordEncode encoder;

public void add(Admin admin){

//先是加密

String newpass=encoder.encoder(admin,getPassword());//加密后的密码

}

public void login(Map<String,String> map){

String loginname=map.get("name");

User user=userService.findLoginname(loginname);

if(user!=null && encode.matches(map.get("password"),user.getPassword)){//参数1是当前用户登录的密码,参数2是数据库的加密数

println("吊毛登录成功密码正确");

}else{

println("吊毛登录密码错误!");

}

}

看到这个图应该懂matches()方法怎么验证新旧密码了!

接下来讲讲流行的权限验证!

Token Auth:

1. 客户端使用用户名跟密码请求登录
2. 服务端收到请求,去验证用户名与密码
3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里
5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向
客户端返回请求的数据

token机制相比较Cookie机制的优点有以下几点!

1.支持跨域访问:Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提
是传输的用户认证信息通过HTTP头传输

2.无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为
Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储
状态信息.

3.CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防

下面讲讲怎么生成这么优秀的token:

基于JWT的token认证机制实现!

然而有个问题就是JWT是个啥!

它就是就是JSON WEB  TOKEN(JWT)是一个轻巧的规范!可以利用这个规范来回于客户端和服务器之间传递信息!

JWT的组成:

一个规范的JWT其实就是一个很长的字符串!但是它由三部分生成!头部(Header),载荷还有签名。

头部(Header)

用于描述基本的JWT信息,列如其类型,以及签名的算法。

{"typ":"jwt","alg":"HS256"}

可以去这个网站尝试下:http://tool.oschina.net/encrypt/

载荷(playload)

这个呢就是存放有效的信息,有效信息包含三个部分!

(1)标准中注册的声明

iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击

(2)公共的声明

可以添加任何信息,一般就是添加用户相关的信息,或是其他一些必要的信息。这部分在客户端是可以解密的!

(3)私有的声明

这个是生产者和消费者所共同定义的声明,一般不建议存放小秘密,base64是解密的。

这个指的就是自定义的claim。比如前面那个结构举例中的admin和name都属于自定的
claim。这些claim跟JWT标准规定的claim区别在于:JWT规定的claim,JWT的接收方在
拿到JWT之后,都知道怎么对这些标准的claim进行验证(还不知道是否能够验证);而
private claims不会验证,除非明确告诉接收方要对这些claim进行验证以及规则才行。

定义个载荷:(payload )

{"sub":"1234567890","name":"John Doe","admin":true}

然后进行编码得到JWT的第二部分:

U2FsdGVkX1+cUgHYwPAxxcIVZic0nHS4NaJ/OvqQ4ECoTyQOKxK75NV2txe25qyz
8YMjvKNpwZyaK6/m6cZy3UugCh+XQKnqkZbdCNDBdmI=

签证(signature)

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符
串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第
三部分.

TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6I
kpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7Hg
Q

secret(可以理解成秘钥)是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用
来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流
露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

下面讲讲怎么使用Java实现JWT,那就是JJWT

问题来了什么是JJWT呢?

其实就是一个提供客户端到服务端的JWT创建和验证的JAVA库。

在项目中如何使用呢?

在maven工程中引入依赖

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

下面这段代码测试下:

public class CreateJwtTest {
    public static void main(String[] args) {
JwtBuilder builder= Jwts.builder().setId("123")
        .setSubject("小菜鸟")
        .setIssuedAt(new Date())
        .signWith(SignatureAlgorithm.HS256,"ousuhao");
System.out.println( builder.compact() );
    }
}

输出的内容是:jsonwebtoken.impl.DefaultJwtBuilder@5c7fa833

每次生成的都不一样,因为载荷里面加了当前的时间。

讲了生成token,那么下面讲讲怎么解析,因为在web应用中这个操作是由服务端进行然后发给客户端的,下次客户端要想访问就要提供token.那么服务端接到这个token应该接解析出token中的用户id,根据用户id查询用户相关的详细数据。

下面是解析代码!

public class ParseJwtTest {
    public static void main(String[] args) {
        String token="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMjMiLCJzdWIiOiLlsI_oj5zpuJ8iLCJpYXQiOjE1NTE3NjMxMzl9.DoKFDkgvNX3WR7cRv9bSfBq9LB6hdBSLqEIWIyGLlDs";
        Claims claims=Jwts.parser().setSigningKey("ousuhao").parseClaimsJws(token).getBody();
        System.out.println("id"+claims.getId());
        System.out.println("subject"+claims.getSubject());
        System.out.println("IssuedAt"+claims.getIssuedAt());
    }
}

下面介绍下过期的编写!

public class CreateJwtTest2 {
    public static void main(String[] args) {
        //为了方便测试,我们将过期的时间,设置为1分钟。
        long now =System.currentTimeMillis();//当前时间
        long exp= now+1000*60;//比当前时间多一分钟
        JwtBuilder builder = Jwts.builder();
        builder.setId("321")
                .setSubject("叫爸爸")
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256,"ousuhao")
                .setExpiration(new Date(exp));
        System.out.println();
        //ousuhao:这个是秘钥不能写中文,不然就报错
        System.out.println(builder.compact());
    }
}
public class ParseJwtTest2 {
    public static void main(String[] args) {
        //下面这个jwt字符串受过期影响
        String jwt="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIzMjEiLCJzdWIiOiLlj6vniLjniLgiLCJpYXQiOjE1NTE3NzQ4OTIsImV4cCI6MTU1MTc3NDk1MX0.qmQLhl7WLco3429MRhznOKP3q-Q9oq8V0bADPRUEVBk";
        Claims claims= Jwts.parser().setSigningKey("ousuhao").parseClaimsJws(jwt).getBody();
        System.out.println("id"+claims.getId());
        System.out.println("subject"+claims.getSubject());
        System.out.println("roles:"+claims.get("roles"));
        System.out.println("logo:"+claims.get("logo"));

        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        System.out.println("签发时间:"+sdf.format(claims.getIssuedAt()));
        System.out.println("过期时间:"+sdf.format(claims.getExpiration()));
        System.out.println("当前时间:"+sdf.format(new Date()));

    }
}

以上是关于JJWT生成的完整解释,要是有不懂的!欢迎下方评论!

猜你喜欢

转载自blog.csdn.net/weixin_41244495/article/details/88144148