项目搭建笔记
不从数据库中读取用户信息
不需要实现UserDetails 和 UserDetailsService 接口
一个是用来保存用户认证及权限信息的,另外一个是用来获取用户信息的
如果我们需要从外部数据源中获取用户信息就需要实现这两个接口,但是这里由于我们需要在内存中实现,所以我们不需要弄这两个东西
由于是在内存中校验,所以这里的密码可以选择不加密
/**
* 在内存中构建静态用户以及权限
*
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(username).password(password).roles("admin")
.and()
.passwordEncoder(NoOpPasswordEncoder.getInstance());
}
自定义注解实现匿名访问
使用方式,将注解标注在类或方法上
然后使用处理器中的 public String[] getAnonymousUrl()
方法获取匿名访问路径的数组
在SpringSecurity的配置类中进行配置
import com.panda.common.annotation.NoLoginVerify;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author mahe666
* @date 2022/12/1
*/
@Component
public class NoLoginVerifyHandler {
protected final Logger logger = LoggerFactory.getLogger(NoLoginVerifyHandler.class);
@Resource
private ApplicationContext applicationContext;
/**
* 所有带有RequestMapping的方法
*/
private static Map<RequestMappingInfo, HandlerMethod> handlerMethodMap;
/**
* 待返回的anonymousUrls
*/
private static final Set<String> ANONYMOUS_URLS_SET = new HashSet<>();
/**
* 初始化当前处理器
*/
@PostConstruct
public void init() {
NoLoginVerifyHandler noLoginVerifyHandler = this;
// 获取所有带有RequestMapping注解的方法
handlerMethodMap = noLoginVerifyHandler.applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();
}
/**
* 根据方法上的注解,添加匿名访问路径
*/
private void getAnonymousUrlsByMethodAnnotation() {
handlerMethodMap.entrySet().stream()
// 过滤出包含匿名访问注解的handlerMethodEntry
.filter(handlerMethodEntry -> handlerMethodEntry.getValue().getMethodAnnotation(NoLoginVerify.class) != null)
.forEach(this::addToAnonymousUrls);
}
/**
* 根据类上的注解,添加匿名访问路径
*/
private void getAnonymousUrlsByBeanAnnotation() {
// 获取所有带有匿名访问注解的bean
Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(NoLoginVerify.class);
// 获取所有bean中的所有Method的toString
Set<String> methodNameSet = getMethodNameSet(beansWithAnnotation);
handlerMethodMap.entrySet().stream()
.filter(handlerMethodEntry -> methodNameSet.contains(getMethodNameSet(handlerMethodEntry)))
.forEach(this::addToAnonymousUrls);
}
/**
* 添加到匿名访问set中的具体实现
* @param handlerMethodEntry
* @return
*/
private boolean addToAnonymousUrls(Map.Entry<RequestMappingInfo, HandlerMethod> handlerMethodEntry) {
return ANONYMOUS_URLS_SET.addAll(handlerMethodEntry.getKey().getPatternsCondition().getPatterns());
}
/**
* 获取匿名访问路径的数组
* @return
*/
public String[] getAnonymousUrl() {
getAnonymousUrlsByBeanAnnotation();
getAnonymousUrlsByMethodAnnotation();
logger.info("可以匿名访问的路径为:" + String.join(", ", ANONYMOUS_URLS_SET));
return ANONYMOUS_URLS_SET.toArray(new String[0]);
}
/**
* 获取方法名
* @param mapEntry
* @return String
*/
private String getMethodNameSet(Map.Entry<RequestMappingInfo, HandlerMethod> mapEntry){
return mapEntry.getValue().getMethod().toString();
}
/**
* 获取方法名的Set集合
* @param map
* @return Set<String>
*/
private Set<String> getMethodNameSet(Map<String, Object> map){
return map.values().stream()
.map(bean -> bean.getClass().getMethods())
.flatMap(Arrays::stream)
.map(Objects::toString)
.collect(Collectors.toSet());
}
}
import java.lang.annotation.*;
/**
* 不需要登陆验证 注解
*
* @className: NoLoginVerify
* @author: GuoShunFa
* @date: 2022/11/27
**/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NoLoginVerify {
}