最近看了vuejs,看到了vue-auth中一个jwt-auth,发现几年不关注,前端完全是全新的领域了。
这里列下jwt相关的资源,供快速了解jwt.
https://jwt.io/introduction/
https://github.com/szerhusenBC/jwt-spring-security-demo
https://www.toptal.com/java/rest-security-with-jwt-spring-security-and-java
spring boot security如何集成JWT.
java相关的jwt库太多了。
apache有oltu
spring有spring-security-jwt
还有其它一些第三方开源库
1、服务器端添加 jwt 支持:
配置spring security
package com.elex.gm.spring;
import java.security.SecureRandom;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.elex.gm.service.UserManager;
import com.elex.gm.spring.jwt.JWTAuthenticationFilter;
import com.elex.gm.spring.jwt.JWTLoginFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public BCryptPasswordEncoder passwordEncoder() throws Exception {
        return passwordEncoder;
    }
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/static/**").antMatchers("/hello/**").antMatchers("/api/open/**");
    };
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/api/gm/**").hasAnyRole("ADMIN", "USER")
                .antMatchers("/api/user/**").hasAnyRole("USER")
                .and()
                .formLogin()
                .loginProcessingUrl("/api/user/login")
                .permitAll()
                .and()
                .logout()
                // .logoutUrl("/api/open/logout")
                .and()
                .httpBasic()
                .and()
                .addFilterBefore(new JWTLoginFilter("/api/user/login", authenticationManager()),
                        UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        http.csrf().disable();
        http.headers().frameOptions().disable();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userManager).passwordEncoder(passwordEncoder);
    }
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    }
    @Autowired
    private UserManager userManager;
    private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(16,
            new SecureRandom("j^E1)y*)HL2gT,es+ODa!0+j^L1I3+6I".getBytes()));
}
 
JWTLoginFilter:
package com.elex.gm.spring.jwt;
import java.io.IOException;
import java.util.Map;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import com.alibaba.fastjson.JSON;
import com.elex.gm.model.User;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
    public JWTLoginFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager) {
        super(defaultFilterProcessesUrl);
        setAuthenticationManager(authenticationManager);
    }
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if (username == null) {
            username = "";
        } else {
            username = username.trim();
        }
        if (password == null) {
            password = "";
        } else {
            password = password.trim();
        }
        return getAuthenticationManager()
                .authenticate(new UsernamePasswordAuthenticationToken(username, password, Lists.newArrayList()));
    }
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
            Authentication authResult) throws IOException, ServletException {
        User user = (User) authResult.getPrincipal();
        Map<String, Object> tokenMap = Maps.newHashMap();
        tokenMap.put("id", user.getId());
        tokenMap.put("name", user.getUsername());
        tokenMap.put("roles", user.getRoles());
        Jwt jwt = JwtHelper.encode(JSON.toJSONString(tokenMap), JWTKey.hmac);
        String token = jwt.getEncoded();
        response.setHeader("Authorization", token);
    }
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException failed) throws IOException, ServletException {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
    }
}
JWTAuthentication:
package com.elex.gm.spring.jwt;
import java.io.IOException;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.web.filter.GenericFilterBean;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
public class JWTAuthenticationFilter extends GenericFilterBean {
    private static final String JWT_HEADER = "Authorization";
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        try {
            String token = ((HttpServletRequest) request).getHeader(JWT_HEADER);
            Jwt jwt = JwtHelper.decodeAndVerify(token, JWTKey.hmac);
            JSONObject json = JSON.parseObject(jwt.getClaims());
            String username = json.getString("name");
            String roles = json.getString("roles");
            List<SimpleGrantedAuthority> list = Lists.newArrayList();
            if (!StringUtils.isEmpty(roles)) {
                for (String role : roles.split(",")) {
                    if (!StringUtils.isEmpty(role)) {
                        list.add(new SimpleGrantedAuthority("ROLE_" + role));
                    }
                }
            }
            Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, list);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (Exception e) {
            // e.printStackTrace();
        }
        chain.doFilter(request, response);
    }
}
		 
	
近期评论