spring security

WebSecurityConfig.java

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.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;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsServiceImpl userDetailsService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;

public WebSecurityConfig(UserDetailsServiceImpl userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.userDetailsService = userDetailsService;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}

@Bean
public JWTAuthenticationAgentFilter JWTAuthenticationAgentFilterBean() throws Exception {
        return new JWTAuthenticationAgentFilter(authenticationManager());
}

@Bean
public JWTAuthenticationCustomerFilter JWTAuthenticationCustomerFilterBean() throws Exception {
        return new JWTAuthenticationCustomerFilter(authenticationManager());
}


@Bean
public JWTAuthenticationManagerFilter JWTAuthenticationManagerFilterBean() throws Exception {
        return new JWTAuthenticationManagerFilter(authenticationManager());
}

@Bean
public JWTAuthorizationFilter JWTAuthorizationFilterBean() throws Exception {
        return new JWTAuthorizationFilter(authenticationManager());
}

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // 由于使用的是JWT,我们这里不需要csrf
                .csrf().disable()
                .exceptionHandling()
                //access fail
                //.authenticationEntryPoint(authEntryPoint)
                //role fail
                //.accessDeniedHandler(authAccessDenied)
                .and()
                // 基于token,所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .headers().frameOptions().sameOrigin()
                .and()
                .authorizeRequests()
                // 允许对于网站静态资源的无授权访问
                .antMatchers("/favicon.ico").permitAll()
                .antMatchers("/swagger-ui.html", "/webjars/springfox-swagger-ui/**", "/swagger-resources/**", "/v2/api-docs").permitAll()

                .antMatchers(HttpMethod.POST, "/user/user_agent", "/user/user_agent/password_reset").permitAll()
                .antMatchers(HttpMethod.GET, "/user/user_agent/info_of_register", "/user/user_agent/phone_exist").permitAll()

                .antMatchers(HttpMethod.POST, "/user/user_customer", "/user/user_customer/password_reset").permitAll()
                .antMatchers(HttpMethod.GET, "/user/user_customer/phone_exist").permitAll()

                .antMatchers(HttpMethod.POST, "/user/user_manager").permitAll()

                .antMatchers(HttpMethod.POST, "/file/upload").permitAll()

                .antMatchers(HttpMethod.GET, "/product/group", "/product/product_base", "/product/product_base/one_001/**", "/product/product_info", "/product/product_specific/type_list/**").permitAll()

                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated().and()
                // login filter
                .addFilterBefore(JWTAuthenticationAgentFilterBean(), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(JWTAuthenticationCustomerFilterBean(), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(JWTAuthenticationManagerFilterBean(), UsernamePasswordAuthenticationFilter.class)
                .addFilter(JWTAuthorizationFilterBean())
                // auth filter
                // 禁用缓存
                .headers().cacheControl();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // Create a default account
        auth.userDetailsService(this.userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
}

AuthLoginFilter.java

import com.google.common.base.Strings;
import com.jianjian.shop.common.constant.BusinessType;
import org.springframework.beans.factory.annotation.Value;
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.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class JWTAuthenticationManagerFilter extends AbstractAuthenticationProcessingFilter {
private static String tokenHeader;
private static String tokenPrefix;

@Value("${jwt.header}")
public void setTokenHeader(String value) {
        tokenHeader = value;
}

@Value("${jwt.tokenPrefix}")
public void setTokenPrefix(String value) {
        tokenPrefix = value;
}

public JWTAuthenticationManagerFilter(AuthenticationManager authenticationManager) {
        super(new AntPathRequestMatcher("/login_manager", "POST"));
        setAuthenticationManager(authenticationManager);
}

@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {
        return this.getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(obtainUsername(req) + "__" + BusinessType.UserType.user_manager.name() + "__", obtainPassword(req)));
}

@Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException {
        res.setHeader("content-type", "application/json;charset=UTF-8");
        String token = JWTTokenUtil.tokenGenerate((UserDetailsImpl) auth.getPrincipal());
        if (!Strings.isNullOrEmpty(token)) {
                res.addHeader(tokenHeader, tokenPrefix + token);
        }
        res.getWriter().print("{\"result_code\":\"0\"}");
}

private static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
private static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";

private String obtainPassword(HttpServletRequest request) {
        return request.getParameter(SPRING_SECURITY_FORM_PASSWORD_KEY);
}

private String obtainUsername(HttpServletRequest request) {
        return request.getParameter(SPRING_SECURITY_FORM_USERNAME_KEY);
}
}

AuthFilter.java

import com.google.common.base.Strings;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import org.springframework.beans.factory.annotation.Value;
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.util.Collections;
import java.util.Date;

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
private static String tokenHeader;
private static String tokenPrefix;

@Value("${jwt.header}")
public void setTokenHeader(String value) {
        tokenHeader = value;
}

@Value("${jwt.tokenPrefix}")
public void setTokenPrefix(String value) {
        tokenPrefix = value;
}

public JWTAuthorizationFilter(AuthenticationManager authManager) {
        super(authManager);
}

@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        String header = req.getHeader(tokenHeader);
        if (header == null || !header.startsWith(tokenPrefix)) {
                chain.doFilter(req, res);
                logger.info("无认证");
                return;
        }
        String token = header.replace(tokenPrefix, "");
        try {
                Claims claims = JWTTokenUtil.tokenParse(token);
                if (claims != null && claims.containsKey("userUuid") && !Strings.isNullOrEmpty(claims.get("userUuid").toString())) {
                        if (claims.getExpiration().after(new Date())) {
                                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(claims, null, Collections.emptyList());
                                SecurityContextHolder.getContext().setAuthentication(authentication);
                        } else {
                                logger.warn("失效");
                        }
                }
        } catch (IllegalArgumentException e) {
                logger.error("an error occured during getting username from token", e);
        } catch (SignatureException | MalformedJwtException e) {
                logger.error("Authentication Failed. Username or Password not valid.");
        } catch (ExpiredJwtException e) {
                logger.warn("the token is expired and not valid anymore", e);
        }
        chain.doFilter(req, res);
}
}

AuthEntryPoint.java

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class AuthEntryPoint implements AuthenticationEntryPoint {
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
                System.out.println(authException.getMessage());
                //Full authentication is required to access this resource
                response.setHeader("content-type", "application/json;charset=UTF-8");
                String error = response.getHeader("authError");
                if (error != null && !StringUtils.isEmpty(error))
                        response.getWriter().print(error);
        }
}

AuthAccessDenied.java

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class AuthAccessDenied implements AccessDeniedHandler {
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                System.out.println(accessDeniedException.getMessage());
        }
}

AuthUserDetailsService.java

import com.jianjian.shop.common.constant.BusinessType;
import com.jianjian.shop.domain.usercenter.po.UserAgent;
import com.jianjian.shop.domain.usercenter.po.UserCustomer;
import com.jianjian.shop.domain.usercenter.po.UserManager;
import com.jianjian.shop.domain.usercenter.vo.UserBaseVO_001;
import com.jianjian.shop.security.repository.UserAgentRepository;
import com.jianjian.shop.security.repository.UserCustomerRepository;
import com.jianjian.shop.security.repository.UserManagerRepository;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Optional;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserAgentRepository userAgentRepository;
private final UserCustomerRepository userCustomerRepository;
private final UserManagerRepository userManagerRepository;

public UserDetailsServiceImpl(UserAgentRepository userAgentRepository, UserCustomerRepository userCustomerRepository, UserManagerRepository userManagerRepository) {
 this.userAgentRepository = userAgentRepository;
 this.userCustomerRepository = userCustomerRepository;
 this.userManagerRepository = userManagerRepository;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
 UserBaseVO_001 userBaseVO_001;
 if (username.endsWith("__" + BusinessType.UserType.user_agent.name() + "__")) {
  Optional userAgentOptional = this.userAgentRepository.findByFPhone(username.replace("__" + BusinessType.UserType.user_agent.name() + "__", ""));
  if (!userAgentOptional.isPresent()) {
   throw new UsernameNotFoundException("用户不存在");
  }
  UserAgent userAgent = userAgentOptional.get();
  userBaseVO_001 = UserBaseVO_001.builder()
          .userName(userAgent.getFPhone())
          .password(userAgent.getUserBase().getFPassword())
          .userType(userAgent.getUserBase().getFUserType())
          .uuid(userAgent.getId())
          .build();
 } else if (username.endsWith("__" + BusinessType.UserType.user_customer.name() + "__")) {
  Optional userCustomerOptional = this.userCustomerRepository.findByFPhone(username.replace("__" + BusinessType.UserType.user_customer.name() + "__", ""));
  if (!userCustomerOptional.isPresent()) {
   throw new UsernameNotFoundException("用户不存在");
  }
  UserCustomer userCustomer = userCustomerOptional.get();
  userBaseVO_001 = UserBaseVO_001.builder()
          .userName(userCustomer.getFPhone())
          .password(userCustomer.getUserBase().getFPassword())
          .userType(userCustomer.getUserBase().getFUserType())
          .uuid(userCustomer.getId())
          .build();
 } else if (username.endsWith("__" + BusinessType.UserType.user_manager.name() + "__")) {
  Optional userManagerOptional = this.userManagerRepository.findByFPhone(username.replace("__" + BusinessType.UserType.user_manager.name() + "__", ""));
  if (!userManagerOptional.isPresent()) {
   throw new UsernameNotFoundException("用户不存在");
  }
  UserManager userManager = userManagerOptional.get();
  userBaseVO_001 = UserBaseVO_001.builder()
          .userName(userManager.getFPhone())
          .password(userManager.getUserBase().getFPassword())
          .userType(userManager.getUserBase().getFUserType())
          .uuid(userManager.getId())
          .build();
 } else {
  throw new UsernameNotFoundException("用户不存在");
 }
 return new UserDetailsImpl(userBaseVO_001.getUserName(), userBaseVO_001.getPassword(), Collections.emptyList(), userBaseVO_001.getUuid(), userBaseVO_001.getUserType());
}
}

AuthUser.java

import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;

import java.util.Collection;

@Getter
class UserDetailsImpl extends User {
private final String userUuid;
private final String userType;

UserDetailsImpl(String username, String password, Collection authorities, String userUuid, String userType) {
        super(username, password, authorities);
        this.userUuid = userUuid;
        this.userType = userType;
}
}

JWTTokenUtil.java

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;

@Component
public class JWTTokenUtil {
private static long expirationTime;
private static String secret;

@Value("${jwt.expirationTime}")
public void setExpirationTime(long value) {
        expirationTime = value;
}

@Value("${jwt.secret}")
public void setSecret(String value) {
        secret = value;
}

public static String tokenGenerate(UserDetailsImpl userDetails) {
        return Jwts.builder()
                .setClaims(new HashMap() {{
                        put("userUuid", userDetails.getUserUuid());
                        put("userType", userDetails.getUserType());
                }})
                .setSubject(userDetails.getUserUuid())
                .setIssuer("jianjian")
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + expirationTime))
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
}

public static Claims tokenParse(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
}

/*private  R getClaimFromToken(String token, Function claimsResolver) {
        final Claims claims = tokenParse(token);
        return claimsResolver.apply(claims);
}*/
}

你可能感兴趣的:(spring security)