Service
public interface UserService extends UserDetailsService { } @Service @Transactional public class UserServiceImpl implements UserService { @Autowired private UserMapper mapper; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { UserPojo user = mapper.queryByUserName(s); return user; } }
自定义认证过滤器
package com.dpb.filter; import com.dpb.config.RsaKeyProperties; import com.dpb.domain.RolePojo; import com.dpb.domain.UserPojo; import com.dpb.utils.JwtUtils; import com.fasterxml.jackson.databind.ObjectMapper; import net.bytebuddy.agent.builder.AgentBuilder; 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.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @program: springboot-54-security-jwt-demo * @description: * @author: 波波烤鸭 * @create: 2019-12-03 11:57 */ public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter { private AuthenticationManager authenticationManager; private RsaKeyProperties prop; public TokenLoginFilter(AuthenticationManager authenticationManager, RsaKeyProperties prop) { this.authenticationManager = authenticationManager; this.prop = prop; } public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { try { UserPojo sysUser = new ObjectMapper().readValue(request.getInputStream(), UserPojo.class); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(sysUser.getUsername(), sysUser.getPassword()); return authenticationManager.authenticate(authRequest); }catch (Exception e){ try { response.setContentType("application/json;charset=utf-8"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); PrintWriter out = response.getWriter(); Map resultMap = new HashMap(); resultMap.put("code", HttpServletResponse.SC_UNAUTHORIZED); resultMap.put("msg", "用户名或密码错误!"); out.write(new ObjectMapper().writeValueAsString(resultMap)); out.flush(); out.close(); }catch (Exception outEx){ outEx.printStackTrace(); } throw new RuntimeException(e); } } public void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { UserPojo user = new UserPojo(); user.setUsername(authResult.getName()); user.setRoles((List<RolePojo>)authResult.getAuthorities()); String token = JwtUtils.generateTokenExpireInMinutes(user, prop.getPrivateKey(), 24 * 60); response.addHeader("Authorization", "Bearer "+token); try { response.setContentType("application/json;charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); PrintWriter out = response.getWriter(); Map resultMap = new HashMap(); resultMap.put("code", HttpServletResponse.SC_OK); resultMap.put("msg", "认证通过!"); out.write(new ObjectMapper().writeValueAsString(resultMap)); out.flush(); out.close(); }catch (Exception outEx){ outEx.printStackTrace(); } } }
自定义校验token的过滤器
package com.dpb.filter; import com.dpb.config.RsaKeyProperties; import com.dpb.domain.Payload; import com.dpb.domain.UserPojo; import com.dpb.utils.JwtUtils; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; /** * @program: springboot-54-security-jwt-demo * @description: * @author: 波波烤鸭 * @create: 2019-12-03 12:39 */ public class TokenVerifyFilter extends BasicAuthenticationFilter { private RsaKeyProperties prop; public TokenVerifyFilter(AuthenticationManager authenticationManager, RsaKeyProperties prop) { super(authenticationManager); this.prop = prop; } public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String header = request.getHeader("Authorization"); if (header == null || !header.startsWith("Bearer ")) { //如果携带错误的token,则给用户提示请登录! chain.doFilter(request, response); response.setContentType("application/json;charset=utf-8"); response.setStatus(HttpServletResponse.SC_FORBIDDEN); PrintWriter out = response.getWriter(); Map resultMap = new HashMap(); resultMap.put("code", HttpServletResponse.SC_FORBIDDEN); resultMap.put("msg", "请登录!"); out.write(new ObjectMapper().writeValueAsString(resultMap)); out.flush(); out.close(); } else { //如果携带了正确格式的token要先得到token String token = header.replace("Bearer ", ""); //验证tken是否正确 Payload<UserPojo> payload = JwtUtils.getInfoFromToken(token, prop.getPublicKey(), UserPojo.class); UserPojo user = payload.getUserInfo(); if(user!=null){ UsernamePasswordAuthenticationToken authResult = new UsernamePasswordAuthenticationToken(user.getUsername(), null, user.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authResult); chain.doFilter(request, response); } } } }
编写SpringSecurity的配置类
package com.dpb.config; import com.dpb.filter.TokenLoginFilter; import com.dpb.filter.TokenVerifyFilter; import com.dpb.service.UserService; 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.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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.crypto.bcrypt.BCryptPasswordEncoder; /** * @program: springboot-54-security-jwt-demo * @description: * @author: 波波烤鸭 * @create: 2019-12-03 12:41 */ @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled=true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserService userService; @Autowired private RsaKeyProperties prop; @Bean public BCryptPasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } //指定认证对象的来源 public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); } //SpringSecurity配置信息 public void configure(HttpSecurity http) throws Exception { http.csrf() .disable() .authorizeRequests() .antMatchers("/user/query").hasAnyRole("ADMIN") .anyRequest() .authenticated() .and() .addFilter(new TokenLoginFilter(super.authenticationManager(), prop)) .addFilter(new TokenVerifyFilter(super.authenticationManager(), prop)) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); } }
启动服务测试
启动服务
通过Postman来访问测试
根据token信息我们访问其他资源