当前位置: 移动技术网 > IT编程>开发语言>Java > Spring security学习笔记(二)

Spring security学习笔记(二)

2018年09月19日  | 移动技术网IT编程  | 我要评论

对比两种承载认证信息的方式: session vs token

token验证方案:

session验证方案:

session即会话是将用户信息保存在服务端,根据请求携带的session_id,从服务端存储(通常是redis)里提取出session。token即令牌是将用户信息保存在请求中,不过是加密后的值,在服务端需要对token进行解密,从而提取用户信息。

浅尝jwt(json web token)

jwt的使用场景:

authentication: 这是jwt最常见的应用场景。当用户登陆之后,接下来的每个请求都会携带这个jwt信息。单点登录基本上使用它。
information exchange: jwt是一种安全的多点之间信息传输的方式,因为它使用了签名。
jwt的构成:

  • header
  • payload
  • signature

因此一个jwt看上去是长这样的:
xxxxxx.yyyyy.zzzzzz

在此之前,我们将用户登陆后的认证信息保存在securitycontextholder中,用户登陆信息保存在threadlocal中,理论上不能保证同一用户下一个请求是否被挡。这里将之前提到的spring security认证方式改成使用token进行认证。

@slf4j
public class passwordauthenticationfilter extends   usernamepasswordauthenticationfilter {
private authenticationmanager authenticationmanager;

passwordauthenticationfilter(authenticationmanager authenticationmanager) {
    this.authenticationmanager = authenticationmanager;
}


@override
public authentication attemptauthentication(httpservletrequest request, httpservletresponse response)
        throws authenticationexception {
    log.info("hello");
    try {
        abstractauthenticationtoken authrequest = buildauthentication(request);
        return this.authenticationmanager.authenticate(authrequest);
    } catch (exception failed) {
        throw new authenticationfailedexception("认证失败");
    }
}

@override
protected void successfulauthentication(httpservletrequest request, httpservletresponse response,
                                        filterchain chain, authentication authresult) throws ioexception, servletexception {
    response.addheader("authorization", "abcdefg");
}

private abstractauthenticationtoken buildauthentication(httpservletrequest request) throws ioexception {
    logininfo logininfo = new objectmapper().readvalue(request.getinputstream(), logininfo.class);
    log.info("login info is " + logininfo);
    return new usernameandpasswordauthenticationtoken(logininfo.getname(), logininfo.getpassword());
    }
}

这个filter extends usernamepasswordauthenticationfilter, 默认只对url为/login的请求进行登陆认证。

认证成功之后,在请求头部加token信息。下次请求来的时候,会有一个tokenauthenticationfilter对token进行验证。
这里随意用了一个token,该token没有携带用户信息,只用来验证是否有权限访问请求。

public class tokenauthenticationfilter extends basicauthenticationfilter {

public tokenauthenticationfilter(authenticationmanager authenticationmanager) {
    super(authenticationmanager);
}


@override
protected void dofilterinternal(httpservletrequest request, httpservletresponse response, filterchain filterchain) throws servletexception, ioexception {
    string token = request.getheader("authorization");
    if(!token.equals("abcdefg")) {
        filterchain.dofilter(request, response);
    } else {
        usernameandpasswordauthenticationtoken usernameandpasswordauthenticationtoken =  new usernameandpasswordauthenticationtoken();
        usernameandpasswordauthenticationtoken.setauthenticated(true);
        securitycontextholder.getcontext().setauthentication(usernameandpasswordauthenticationtoken);
        filterchain.dofilter(request, response);
    }

    }
}

如果我们header里不带token,返回结果是403 forbidden。

如果携带token就能成功访问请求api了。

接下来使用jwt来创建和使用token。

在passwordauthenticationfilter认证成功之后,生成一个jwt存在请求返回头里。

在tokenauthenticationfilter的filter流程中,首先增加jwt校验:

然后就实现了使用jwt的方式认证。

代码git repo: https://github.com/rying/twitter-clone.git

参考:

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网