SpringBoot #3:spring boot集成spring-boot-starter-security & jjwt实现权限验证

这篇文章是建立在第一篇,spring boot住在jpa, swagger2, loggin,第二篇,springboot集成redis缓存基础上的,这里主要介绍如何使用jwt & spring-boot-starter-security实现api的保护。

RESTful资源是无状态的,但是我们写的API可能也不会是让人随意调,所以要给API加上调用权限验证,为了能更好的适用移动端、h5、或其它终端调用,我选择jwt配合spring-boot-starter-security来验证。

SpringBoot #3:spring boot集成spring-boot-starter-security & jjwt实现权限验证_第1张图片
jwt-struct.jpg

客户端发送用户验证信息到服务器,服务器根据用户信息生成一段加密的密文(Token),验证通过后,客户端的所有请求都在http header中附加上token。至于jwt的原理些这里就不详细介绍了,感兴趣的可以搜一搜。

下面介绍怎么在项目里进行配制,把api难使用起来。

  • 添加引用

在*.gradle文件中添加jjwt和security的引用

compile ("org.springframework.boot:spring-boot-starter-security")
compile ("io.jsonwebtoken:jjwt:${jjwtVersion}")
  • 在application.yml中配置jwt的一些值
#jwt
jwt:
  header: Authorization
  secret: yoursecret
  expiration: 604800
  tokenHead: "Bearer "
  • 配制security适配器
package leix.lebean.sweb.common.config;

import leix.lebean.sweb.auth.secruity.AuthenticationEntryPoint;
import leix.lebean.sweb.auth.secruity.AuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Name:WebSecurityConfig
 * Description:
 * Author:leix
 * Time: 2017/6/12 10:06
 */
@SuppressWarnings("SpringJavaAutowiringInspection")
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private AuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
                .userDetailsService(this.userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new AuthenticationTokenFilter();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers(HttpMethod.POST, "/users")
                .antMatchers("/", "/auth/**", "/resources/**", "/static/**", "/public/**", "/webui/**", "/h2-console/**"
                        , "/configuration/**", "/swagger-ui/**", "/swagger-resources/**", "/api-docs", "/api-docs/**", "/v2/api-docs/**"
                        , "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.gif", "/**/*.svg", "/**/*.ico", "/**/*.ttf", "/**/*.woff");
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // 由于使用的是JWT,我们这里不需要csrf
                .csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                // 基于token,所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                // 允许对于网站静态资源的无授权访问
                .antMatchers(
                        HttpMethod.GET,
                        "/",
                        "/*.html",
                        "/favicon.ico",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js"
                ).permitAll()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated();

        // 添加JWT filter
        httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
        // 禁用缓存
        httpSecurity.headers().cacheControl();
    }
}

  • 新建一个auth的业务模块

创建与验证业务相关的模块auth,并在auth中实现用户的验证、token的刷新。

AuthController

package leix.lebean.sweb.auth;

/**
 * Name:AuthController
 * Description:用户认证接口
 * Author:leix
 * Time: 2017/6/12 09:42
 */
@RestController
@Api(value = "认证服务", description = "与用户认证相关的服务", position = 1)
public class AuthController extends BaseController {

    @Value("${jwt.header}")
    private String tokenHeader;

    @Autowired
    IAuthService authService;

    @PostMapping("/auth")
    @ApiOperation(value = "用户认证", notes = "用户信息认证服务,用户登录名与密码,返回验证结果")
    @ApiImplicitParam(name = "authentication", value = "用户登录信息", dataType = "Authentication")
    public ResponseEntity auth(@RequestBody Authentication authentication) {
        String token = authService.login(authentication.getName(), authentication.getPassword());
        return ResponseEntity.ok(new AuthenticationResponse(token));
    }

    @GetMapping("/auth")
    @ApiOperation(value = "刷新TOKEN", notes = "刷新用户Token服务")
    public ResponseEntity refreshAndGetAuthenticationToken(
            HttpServletRequest request) throws AuthenticationException {
        String token = request.getHeader(tokenHeader);
        String refreshedToken = authService.refresh(token);
        if (refreshedToken == null) {
            return ResponseEntity.badRequest().body(null);
        } else {
            return ResponseEntity.ok(new AuthenticationResponse(refreshedToken));
        }
    }
}

详细代码来看这里看这里吧!源码@github

你可能感兴趣的:(SpringBoot #3:spring boot集成spring-boot-starter-security & jjwt实现权限验证)