目录
maven 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
文件目录
SpringSecurityConfig
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
DefaultPasswordEncoder defaultPasswordEncoder;
@Autowired
SelfUserDetailsService selfUserDetailsService;
@Autowired
AppFilterInvocationSecurityMetadataSource appFilterInvocationSecurityMetadataSource;
@Autowired
CustomerAccessDecisionManger customerAccessDecisionManger;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 加入自定义的安全认证
// auth.authenticationProvider(provider);
auth.userDetailsService(selfUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
//未授权处理
.authenticationEntryPoint(new UnauthorizedEntryPoint())
.accessDeniedHandler(new MyAccessDeniedHandler())
.and().authorizeRequests().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O o) {
o.setSecurityMetadataSource(appFilterInvocationSecurityMetadataSource);
o.setAccessDecisionManager(customerAccessDecisionManger);
return o;
}
})
.anyRequest().authenticated()
.and().csrf().disable()
.logout().logoutUrl("/logout")
.and()
//.addLogoutHandler(new TokenLogoutHandler(tokenManager))
.addFilter(new TokenAuthenticationFilter(authenticationManager()))
.addFilter(new TokenLoginFilter(authenticationManager())).httpBasic();
}
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Bean
public DefaultPasswordEncoder CreateEncoder(){
return new DefaultPasswordEncoder();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/Account/**","/index**", "/swagger-ui.html/**");
}
}
selfUserDetails
@Data
@Accessors(chain = true)
public class SelfUserDetails implements UserDetails {
private Set<? extends GrantedAuthority> authorities;//角色配置类
private Account account;//用户实体
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.authorities;
}
@Override
public String getPassword() {
return this.account.getPassword();
}
@Override
public String getUsername() {
return this.account.getName();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public void select(String name){
Account name1 = new Account().selectOne((Wrapper) new MyWrapper().eq("name", name));
this.account=name1;
}
}
SelfUserDetailsService
@Component
public class SelfUserDetailsService implements UserDetailsService {
private String roleName=null;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SelfUserDetails selfUserDetails = new SelfUserDetails();
selfUserDetails.select(username);
if(selfUserDetails.getAccount()==null){
//仍需要细化处理
throw new UsernameNotFoundException("该用户不存在");
}
Set authoritiesSet = new HashSet();
// 模拟从数据库中获取用户角色
Userbyrole userbyrole = new Userbyrole().selectOne((Wrapper) new MyWrapper().eq("userid", selfUserDetails.getAccount().getId()));
GrantedAuthority authority = new SimpleGrantedAuthority(userbyrole.getRole().toString());
this.roleName=userbyrole.getRole().toString();
authoritiesSet.add(authority);
selfUserDetails.setAuthorities(authoritiesSet);
return selfUserDetails;
}
public String getRoleName(){
return this.roleName;
}
}
DefaultPasswordEncoder
@Slf4j
public class DefaultPasswordEncoder extends BCryptPasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
return rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (rawPassword == null) {
throw new IllegalArgumentException("rawPassword cannot be null");
}
if (encodedPassword == null || encodedPassword.length() == 0) {
log.error("Empty encoded password");
throw new IllegalArgumentException("encodedPassword is null");
}
return encodedPassword.equals(rawPassword);
}
}
JwtTokenUtil
public class JwtTokenUtil {
private static long tokenExpiration = 24 * 60 * 60 * 1000;
private static String tokenSignKey = "123456";
private static String userRoleKey = "userRole";
public String createToken(String userName) {
String token = Jwts.builder().setSubject(userName)
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
.signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact();
return token;
}
public static String createToken(String userName, String role) {
String token = Jwts.builder().setSubject(userName)
.claim(userRoleKey, role)
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
.signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact();
return token;
}
public static String getUserNameFromToken(String token) {
String userName = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody().getSubject();
return userName;
}
public static String getUserRoleFromToken(String token) {
Claims claims = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody();
return claims.get(userRoleKey).toString();
}
}
MyAccessDenieDHandler
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setStatus(403);
ResponseUtil.out(response, Result.failed("权限不足"));
}
}
TokenAuthenticationFilter
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
public TokenAuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
private void PassUp(HttpServletRequest request, HttpServletResponse response, FilterChain chain, String... url) throws IOException, ServletException {
for (int i = 0; i < url.length; i++) {
if(request.getRequestURL().indexOf(url[i])!=-1)
chain.doFilter(request,response);
}
}
private void NotAllowed(HttpServletRequest request, HttpServletResponse response, FilterChain chain){
if(!request.getMethod().contains("POST")){//必须是POST请求
try{
ResponseUtil.out(response, Result.failed("不是POST!"));
chain.doFilter(request,response);
}catch (Exception e) {
logger.debug(e.getMessage());
}
}
}
private void TokenVerify(HttpServletRequest request, HttpServletResponse response, FilterChain chain){
UsernamePasswordAuthenticationToken authenticationToken=null;
try{
authenticationToken=getAuthentication(request);//或取请求中的Token信息
if (authenticationToken != null) {//Token令牌为null
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
} else {
ResponseUtil.out(response, Result.failed("鉴权失败"));
}
}catch (Exception e){
e.printStackTrace();
ResponseUtil.out(response, Result.failed(e.getMessage()));
}
try{
chain.doFilter(request, response);
}catch (Exception e){
logger.debug(e.getMessage());
}
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.info("==========================="+request.getRequestURL());
PassUp(request,response,chain,"index");
NotAllowed(request,response,chain);
TokenVerify(request,response,chain);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
// 获取Token字符串,token 置于 header 里
String token = request.getHeader("token");
if (!StringUtils.hasText(token)) {
token = request.getParameter("token");
}
if (token != null && !"".equals(token.trim())) {
// 从Token中解密获取用户名
String userName = JwtTokenUtil.getUserNameFromToken(token);
if (userName != null) {
// 从Token中解密获取用户角色
String role = JwtTokenUtil.getUserRoleFromToken(token);
// 将ROLE_XXX,ROLE_YYY格式的角色字符串转换为数组
String[] roles = role.split(",");
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
for (String s : roles) {
authorities.add(new SimpleGrantedAuthority(s));
}
return new UsernamePasswordAuthenticationToken(userName, token, authorities);
}
return null;
}
return null;
}
}
TokenLoginFilter
@Slf4j
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
private AuthenticationException authentication;
public TokenLoginFilter(AuthenticationManager authenticationManager) {
this.authenticationManager =authenticationManager;
}
@SneakyThrows
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
String username = request.getParameter("username");
String password = request.getParameter("password");
username = username != null ? username.trim() : "";
password = password != null ? password : "";
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password, new ArrayList<>()));
} catch (Exception e) {
new RuntimeException(e);
this.unsuccessfulAuthentication(request,response, (AuthenticationException) authentication);
return null;
}
}
/**
* 登录成功
*/
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException, ServletException {
SelfUserDetails user= (SelfUserDetails) auth.getPrincipal();
Account account = user.getAccount();
String authrorities = user.getAuthorities().size() > 0 ? user.getAuthorities().toString().replaceAll("(?:\\[|null|\\]| +)", "") : user.getAuthorities().toString();
String token=JwtTokenUtil.createToken(account.getName(),authrorities);
HashMap<Object, Object> map = new HashMap<>();
map.put("token", token);
map.put("user",account);
ResponseUtil.out(response, Result.successWithData(map));
}
/**
* 登录失败
*/
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
logger.debug("登录失败!");
ResponseUtil.out(response, Result.failed("登录失败"));
}
}
UnauthorizedEntryPorint
public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
ResponseUtil.out(httpServletResponse, Result.failed("未授权统一处理"));
}
}