当前位置:   article > 正文

SpringBoot3+SpringSecurity整合_springboot3整合security

springboot3整合security
Security导包:
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-security</artifactId>
  4. </dependency>
模拟Redis存储登录信息:
  1. public class CacheEntity implements Serializable {
  2. private Object value;
  3. /**
  4. * 保存的时间戳
  5. */
  6. private long gmtModify;
  7. /**
  8. * 过期时间
  9. */
  10. private int expire;
  11. public Object getValue() {
  12. return value;
  13. }
  14. public void setValue(Object value) {
  15. this.value = value;
  16. }
  17. public long getGmtModify() {
  18. return gmtModify;
  19. }
  20. public void setGmtModify(long gmtModify) {
  21. this.gmtModify = gmtModify;
  22. }
  23. public int getExpire() {
  24. return expire;
  25. }
  26. public void setExpire(int expire) {
  27. this.expire = expire;
  28. }
  29. public CacheEntity(Object value, long gmtModify, int expire) {
  30. this.value = value;
  31. this.gmtModify = gmtModify;
  32. this.expire = expire;
  33. }
  34. }
  1. @Slf4j
  2. public class LocalCache {
  3. /**
  4. * 默认的缓存容量
  5. */
  6. private static final int DEFAULT_CAPACITY = 512;
  7. /**
  8. * 最大容量
  9. */
  10. private static final int MAX_CAPACITY = 100000;
  11. /**
  12. * 刷新缓存的频率
  13. */
  14. private static final int MONITOR_DURATION = 2;
  15. // 启动监控线程
  16. static {
  17. new Thread(new TimeoutTimerThread()).start();
  18. }
  19. // 内部类方式实现单例
  20. private static class LocalCacheInstance {
  21. private static final LocalCache INSTANCE = new LocalCache();
  22. }
  23. public static LocalCache getInstance() {
  24. return LocalCacheInstance.INSTANCE;
  25. }
  26. private LocalCache() {
  27. }
  28. /**
  29. * 使用默认容量创建一个Map
  30. */
  31. private static Map<String, CacheEntity> cache = new ConcurrentHashMap<>(DEFAULT_CAPACITY);
  32. /**
  33. * 将key-value保存到本地缓存并制定该缓存的过期时间
  34. *
  35. * @param key
  36. * @param value
  37. * @param expireTime 过期时间,如果是-1 则表示永不过期
  38. * @param <T>
  39. * @return
  40. */
  41. public <T> boolean putValue(String key, T value, int expireTime) {
  42. return putCloneValue(key, value, expireTime);
  43. }
  44. /**
  45. * 将值通过序列化clone 处理后保存到缓存中,可以解决值引用的问题
  46. *
  47. * @param key
  48. * @param value
  49. * @param expireTime
  50. * @param <T>
  51. * @return
  52. */
  53. private <T> boolean putCloneValue(String key, T value, int expireTime) {
  54. try {
  55. if (cache.size() >= MAX_CAPACITY) {
  56. return false;
  57. }
  58. // 序列化赋值
  59. CacheEntity entityClone = clone(new CacheEntity(value, System.nanoTime(), expireTime));
  60. cache.put(key, entityClone);
  61. return true;
  62. } catch (Exception e) {
  63. log.error("添加缓存失败:{}", e.getMessage());
  64. }
  65. return false;
  66. }
  67. /**
  68. * 序列化 克隆处理
  69. *
  70. * @param object
  71. * @param <E>
  72. * @return
  73. */
  74. private <E extends Serializable> E clone(E object) {
  75. E cloneObject = null;
  76. try {
  77. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  78. ObjectOutputStream oos = new ObjectOutputStream(baos);
  79. oos.writeObject(object);
  80. oos.close();
  81. ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
  82. ObjectInputStream ois = new ObjectInputStream(bais);
  83. cloneObject = (E) ois.readObject();
  84. ois.close();
  85. } catch (Exception e) {
  86. log.error("缓存序列化失败:{}", e.getMessage());
  87. }
  88. return cloneObject;
  89. }
  90. /**
  91. * 从本地缓存中获取key对应的值,如果该值不存则则返回null
  92. *
  93. * @param key
  94. * @return
  95. */
  96. public Object getValue(String key) {
  97. if (CollectionUtils.isEmpty(cache)) {
  98. return null;
  99. }
  100. CacheEntity cacheEntity = cache.get(key);
  101. if (ObjectUtils.isEmpty(cacheEntity)) {
  102. return null;
  103. }
  104. return cacheEntity.getValue();
  105. }
  106. public void remove(String key) {
  107. if (CollectionUtils.isEmpty(cache)) {
  108. return;
  109. }
  110. CacheEntity cacheEntity = cache.get(key);
  111. if (ObjectUtils.isEmpty(cacheEntity)) {
  112. return;
  113. }
  114. cache.remove(key);
  115. }
  116. /**
  117. * 清空所有
  118. */
  119. public void clear() {
  120. cache.clear();
  121. }
  122. /**
  123. * 过期处理线程
  124. */
  125. static class TimeoutTimerThread implements Runnable {
  126. @Override
  127. public void run() {
  128. while (true) {
  129. try {
  130. TimeUnit.SECONDS.sleep(MONITOR_DURATION);
  131. checkTime();
  132. } catch (Exception e) {
  133. log.error("过期缓存清理失败:{}", e.getMessage());
  134. }
  135. }
  136. }
  137. /**
  138. * 过期缓存的具体处理方法 * * @throws Exception
  139. */
  140. private void checkTime() throws Exception {
  141. // 开始处理过期
  142. for (String key : cache.keySet()) {
  143. CacheEntity tce = cache.get(key);
  144. long timoutTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - tce.getGmtModify());
  145. // 过期时间 : timoutTime
  146. if (tce.getExpire() > timoutTime) {
  147. continue;
  148. }
  149. log.info(" 清除过期缓存 :" + key);
  150. //清除过期缓存和删除对应的缓存队列
  151. cache.remove(key);
  152. }
  153. }
  154. }
  155. }
权限枚举:
  1. // 权限值是将二进制与十进制相互转换来判断的
  2. public enum PermissionEnum {
  3. GET_DEPARTMENT(1, "单位获取", "ROLE_GET_DEPARTMENT", 0x0000000000000001L),
  4. INSERT_DEPARTMENT(2, "单位增加", "ROLE_INSERT_DEPARTMENT", 0x0000000000000002L),
  5. UPDATE_DEPARTMENT(3, "单位修改", "ROLE_UPDATE_DEPARTMENT", 0x0000000000000004L),
  6. DELETE_DEPARTMENT(4, "单位删除", "ROLE_DELETE_DEPARTMENT", 0x0000000000000008L),
  7. ;
  8. private int id;
  9. private String permissions;
  10. private String permissionNames;
  11. private Long value;
  12. PermissionEnum(int id, String permissions, String permissionNames, Long value) {
  13. this.id = id;
  14. this.permissions = permissions;
  15. this.permissionNames = permissionNames;
  16. this.value = value;
  17. }
  18. public int getId() {
  19. return id;
  20. }
  21. public void setId(int id) {
  22. this.id = id;
  23. }
  24. public String getPermissions() {
  25. return permissions;
  26. }
  27. public void setPermissions(String permissions) {
  28. this.permissions = permissions;
  29. }
  30. public String getPermissionNames() {
  31. return permissionNames;
  32. }
  33. public void setPermissionNames(String permissionNames) {
  34. this.permissionNames = permissionNames;
  35. }
  36. public Long getValue() {
  37. return value;
  38. }
  39. public void setValue(Long value) {
  40. this.value = value;
  41. }
  42. public static List<GrantedAuthority> fromCode(Long code) {
  43. List<GrantedAuthority> list = new ArrayList<>();
  44. PermissionEnum[] codes = PermissionEnum.values();
  45. for (PermissionEnum state : codes) {
  46. if ((state.getValue() & code) > 0) {
  47. list.add(new SimpleGrantedAuthority(state.getPermissionNames()));
  48. }
  49. }
  50. return list;
  51. }
  52. public static List<PermissionEnum> getAuthList(Long code) {
  53. List<PermissionEnum> list = new ArrayList<>();
  54. PermissionEnum[] codes = PermissionEnum.values();
  55. for (PermissionEnum state : codes) {
  56. if ((state.getValue() & code) > 0) {
  57. list.add(state);
  58. }
  59. }
  60. return list;
  61. }
  62. // 获取权限值
  63. public static Long getPermissionCode(Integer[] auths) {
  64. Long code = 0x0000000000000000L;
  65. PermissionEnum[] codes = PermissionEnum.values();
  66. for (Integer auth : auths) {
  67. for (PermissionEnum permissionCode : codes) {
  68. if (auth.equals(permissionCode.getId())) {
  69. code += permissionCode.getValue();
  70. break;
  71. }
  72. }
  73. }
  74. return code;
  75. }
  76. // 获取权限数组
  77. public static String[] getAuths(Long code) {
  78. List<String> lists = new ArrayList<>();
  79. PermissionEnum[] codes = PermissionEnum.values();
  80. for (PermissionEnum state : codes) {
  81. if ((state.getValue() & code) > 0) {
  82. lists.add(state.getPermissions());
  83. }
  84. }
  85. return lists.toArray(new String[lists.size()]);
  86. }
  87. // 获取权限值
  88. public static Long getPermissionCode(String[] auths) {
  89. Long code = 0x0000000000000000L;
  90. PermissionEnum[] codes = PermissionEnum.values();
  91. for (String auth : auths) {
  92. for (PermissionEnum permissionCode : codes) {
  93. if (auth.equals(permissionCode.getPermissions())) {
  94. code += permissionCode.getValue();
  95. break;
  96. }
  97. }
  98. }
  99. return code;
  100. }
  101. }
User实体类:
  1. @Data
  2. @Accessors(chain = true)
  3. public class Users implements Serializable {
  4. private Long userID;
  5. private String userName;
  6. private String userPassword;
  7. private String userPhone;
  8. private String userAddress;
  9. private Integer userAllowErrCount;
  10. private Integer userErrCount;
  11. private Date userLastErrTime;
  12. private Long userRoleID;
  13. private Roles roles;
  14. private Long userDepID;
  15. private Department department;
  16. private boolean userEnable;
  17. }
权限反序列化:
  1. public class CustomAuthorityDeserializer extends JsonDeserializer {
  2. @Override
  3. public Object deserialize(
  4. JsonParser p, DeserializationContext deserializationContext
  5. ) throws IOException, JacksonException {
  6. ObjectMapper mapper = (ObjectMapper) p.getCodec();
  7. JsonNode jsonNode = mapper.readTree(p);
  8. LinkedList<GrantedAuthority> grantedAuthorities = new LinkedList<>();
  9. Iterator<JsonNode> elements = jsonNode.elements();
  10. while (elements.hasNext()) {
  11. JsonNode next = elements.next();
  12. JsonNode authority = next.get("authority");
  13. //将得到的值放入链表 最终返回该链表
  14. grantedAuthorities.add(new SimpleGrantedAuthority(authority.asText()));
  15. }
  16. return grantedAuthorities;
  17. }
  18. }

用户详情类:

  1. @JsonIgnoreProperties({"enabled", "accountNonExpired", "accountNonLocked", "credentialsNonExpired",
  2. "username", "password"})
  3. public class MyUserDetail extends Users implements UserDetails, Serializable {
  4. List<? extends GrantedAuthority> authorities;
  5. public MyUserDetail() {
  6. }
  7. public MyUserDetail(Users users, List<? extends GrantedAuthority> authList) {
  8. this.setUserID(users.getUserID());
  9. this.setUserName(users.getUserName());
  10. this.setUserPassword(users.getUserPassword());
  11. this.setUserDepID(users.getUserDepID());
  12. this.setUserRoleID(users.getUserRoleID());
  13. this.authorities = authList;
  14. }
  15. @Override
  16. @JsonDeserialize(using = CustomAuthorityDeserializer.class)
  17. public Collection<? extends GrantedAuthority> getAuthorities() {
  18. return this.authorities;
  19. }
  20. @Override
  21. public String getPassword() {
  22. return this.getUserPassword();
  23. }
  24. @Override
  25. public String getUsername() {
  26. return this.getUserName();
  27. }
  28. @Override
  29. public boolean isAccountNonExpired() {
  30. return true;
  31. }
  32. @Override
  33. public boolean isAccountNonLocked() {
  34. return true;
  35. }
  36. @Override
  37. public boolean isCredentialsNonExpired() {
  38. return true;
  39. }
  40. @Override
  41. public boolean isEnabled() {
  42. return true;
  43. }
  44. }
用户详情实现类:
  1. @Component
  2. public class MyUserDetailServiceImpl implements UserDetailsService {
  3. // 操作数据库,根据用户名称查询用户信息
  4. private final UserMapper userMapper;
  5. public MyUserDetailServiceImpl(UserMapper userMapper) {
  6. this.userMapper = userMapper;
  7. }
  8. @Override
  9. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  10. Users users = userMapper.getUserByName(username);
  11. Optional.ofNullable(users).orElseThrow(() -> {
  12. // 自定义的异常返回类和枚举
  13. throw new CommonException(YIXGResultEnum.USER_NOT_EXIST.getCode(),
  14. YIXGResultEnum.USER_NOT_EXIST.getMessage());
  15. });
  16. if (ObjectUtils.isEmpty(users.getUserRoleID())) {
  17. throw new CommonException(YIXGResultEnum.USER_ROLE_NOT_EXIST.getCode(),
  18. YIXGResultEnum.USER_ROLE_NOT_EXIST.getMessage());
  19. }
  20. List<GrantedAuthority> authorityList = PermissionEnum.fromCode(users.getRoles().getRolePermission());
  21. return new MyUserDetail(users, authorityList);
  22. }
  23. }
拦截未登录请求:
  1. /**
  2. * 用户发起未登录的请求会被AuthorizationFilter拦截,并抛出AccessDeniedException异常。异常被AuthenticationEntryPoint
  3. * 处理,默认会触发重定向到登录页。Spring Security开放了配置,允许我们自定义AuthenticationEntryPoint。
  4. * 那么我们就通过自定义AuthenticationEntryPoint来取消重定向行为,将接口改为返回JSON信息。
  5. */
  6. public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
  7. @Override
  8. public void commence(
  9. HttpServletRequest request, HttpServletResponse response, AuthenticationException authException
  10. ) throws IOException, ServletException {
  11. CommonResult commonResult = new CommonResult();
  12. ObjectMapper objectMapper = new ObjectMapper();
  13. commonResult.setCode(YIXGResultEnum.LOGIN_INVALID.getCode())
  14. .setMessage(YIXGResultEnum.LOGIN_INVALID.getMessage());
  15. response.setContentType("application/json;charset=UTF-8");
  16. response.getWriter().write(objectMapper.writeValueAsString(commonResult));
  17. response.getWriter().flush();
  18. response.getWriter().close();
  19. }
  20. }
拦截没权限的请求:
  1. public class MyAccessDeniedHandler implements AccessDeniedHandler {
  2. @Override
  3. public void handle(
  4. HttpServletRequest request, HttpServletResponse response,
  5. AccessDeniedException accessDeniedException
  6. ) throws IOException, ServletException {
  7. ObjectMapper objectMapper = new ObjectMapper();
  8. CommonResult commonResult = new CommonResult();
  9. commonResult.setCode(YIXGResultEnum.NO_PERMISSION.getCode())
  10. .setMessage(YIXGResultEnum.NO_PERMISSION.getMessage());
  11. response.setContentType("application/json;charset=UTF-8");
  12. response.getWriter().write(objectMapper.writeValueAsString(commonResult));
  13. response.getWriter().flush();
  14. response.getWriter().close();
  15. }
  16. }
自定义拦截器,验证token信息:
  1. public class MyAuthenticationTokenFilter extends OncePerRequestFilter {
  2. @Override
  3. protected void doFilterInternal(
  4. HttpServletRequest request, HttpServletResponse response, FilterChain filterChain
  5. ) throws ServletException, IOException {
  6. // 从header中获取验证信息
  7. String authHeader = request.getHeader(GlobalUtil.AUTHORIZATION);
  8. if (ObjectUtils.isEmpty(authHeader)) {
  9. filterChain.doFilter(request, response);
  10. return;
  11. }
  12. this.doParse(request, response, filterChain, authHeader);
  13. }
  14. private void doParse(
  15. HttpServletRequest request, HttpServletResponse response, FilterChain chain, String authHeader
  16. ) throws ServletException, IOException {
  17. ObjectMapper objectMapper = new ObjectMapper();
  18. // 如果认证码 以规定值开头
  19. if (authHeader.startsWith(GlobalUtil.GRANT_TYPE)) {
  20. // 提取token值
  21. String token = authHeader.substring(GlobalUtil.GRANT_TYPE.length());
  22. if (ObjectUtils.isEmpty(token)) {
  23. chain.doFilter(request, response);
  24. return;
  25. }
  26. // 通过token值从缓存中取用户信息
  27. String userJson = (String) LocalCache.getInstance().getValue(token);
  28. // 转换JSON对象
  29. //JSONObject userJsonObject = JSON.parseObject(userJson);
  30. // 判断是否空值
  31. if (ObjectUtils.isEmpty(userJson)) {
  32. // throw new CommonException(YIXGResultEnum.INVALID_TOKEN.getCode(),
  33. // YIXGResultEnum.INVALID_TOKEN.getMsg());
  34. chain.doFilter(request, response);
  35. return;
  36. }
  37. // 转换MyUserDetail对象
  38. MyUserDetail user = objectMapper.readValue(userJson, MyUserDetail.class);
  39. //MyUserDetail user = JSON.toJavaObject(userJsonObject, MyUserDetail.class);
  40. // MyUserDetail user = JSONObject.toJavaObject(userJsonObject, MyUserDetail.class);
  41. // 转换 UP 对象放到上下文中
  42. UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
  43. new UsernamePasswordAuthenticationToken(
  44. user, user.getPassword(), user.getAuthorities());
  45. SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
  46. }
  47. chain.doFilter(request, response);
  48. }
  49. }
密码加密:
  1. public class MyPasswordEncoder implements PasswordEncoder {
  2. @Override
  3. public String encode(CharSequence rawPassword) {
  4. return MD5Util.md5((String) rawPassword);
  5. }
  6. @Override
  7. public boolean matches(CharSequence rawPassword, String encodedPassword) {
  8. return encodedPassword.equalsIgnoreCase(MD5Util.md5((String) rawPassword));
  9. }
  10. }
登录成功:
  1. @Component
  2. public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
  3. private final ObjectMapper objectMapper;
  4. private final LogService logService;
  5. private final UserService userService;
  6. public MyAuthenticationSuccessHandler(
  7. ObjectMapper objectMapper, LogService logService,
  8. UserService userService
  9. ) {
  10. this.objectMapper = objectMapper;
  11. this.logService = logService;
  12. this.userService = userService;
  13. }
  14. @Override
  15. public void onAuthenticationSuccess(
  16. HttpServletRequest request, HttpServletResponse response, FilterChain chain,
  17. Authentication authentication
  18. ) throws IOException, ServletException {
  19. AuthenticationSuccessHandler.super.onAuthenticationSuccess(request, response, chain, authentication);
  20. }
  21. @Override
  22. public void onAuthenticationSuccess(
  23. HttpServletRequest request, HttpServletResponse response, Authentication authentication
  24. ) throws IOException, ServletException {
  25. MyUserDetail user = (MyUserDetail) authentication.getPrincipal();
  26. // 获取随机token 并存到Redis中
  27. String token = UUID.randomUUID().toString().replaceAll("-", "");
  28. LocalCache.getInstance().putValue(token, objectMapper.writeValueAsString(user), 60 * 60);
  29. UserVO userVO = new UserVO();
  30. userVO.setUserName(user.getUserName())
  31. .setUserErrCount("0")
  32. .setUserLastErrTime(null);
  33. userService.updateUserErrCount(userVO);
  34. LogVO logVO = new LogVO();
  35. logVO.setLogOperateUser(user.getUserName())
  36. .setLogContent("登录成功")
  37. .setLogType("登录日志");
  38. logService.addLog(logVO);
  39. CommonResult commonResult = new CommonResult();
  40. commonResult.setCode(YIXGResultEnum.OPERATE_SUCCESS.getCode())
  41. .setMessage(YIXGResultEnum.OPERATE_SUCCESS.getMessage())
  42. .setToken(token)
  43. .setCurrentUser(user.getUserName())
  44. .setCurrentUserId(user.getUserID());
  45. response.setContentType("application/json;charset=UTF-8");
  46. response.getWriter().write(objectMapper.writeValueAsString(commonResult));
  47. response.getWriter().flush();
  48. response.getWriter().close();
  49. }
  50. }
登录失败:
  1. @Component
  2. @Slf4j
  3. public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
  4. private final ObjectMapper objectMapper;
  5. private final UserService userService;
  6. public MyAuthenticationFailureHandler(ObjectMapper objectMapper, UserService userService) {
  7. this.objectMapper = objectMapper;
  8. this.userService = userService;
  9. }
  10. @Override
  11. public void onAuthenticationFailure(
  12. HttpServletRequest request, HttpServletResponse response, AuthenticationException exception
  13. ) throws IOException, ServletException {
  14. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  15. CommonResult result = userService.getUserByUserName(
  16. new UserVO().setUserName(request.getParameter("username")));
  17. Users users = (Users) result.getObjectData();
  18. if (Objects.equals(result.getCode(), YIXGResultEnum.OPERATE_SUCCESS.getCode())) {
  19. UserVO userVO = new UserVO();
  20. userVO.setUserName(users.getUserName())
  21. .setUserErrCount(String.valueOf((users.getUserErrCount() + 1)))
  22. .setUserLastErrTime(sdf.format(new Date()));
  23. userService.updateUserErrCount(userVO);
  24. }
  25. CommonResult commonResult = new CommonResult();
  26. commonResult.setCode(YIXGResultEnum.PASSWORD_OR_USERNAME_ERROR.getCode())
  27. .setMessage(YIXGResultEnum.PASSWORD_OR_USERNAME_ERROR.getMessage());
  28. response.setContentType("application/json");
  29. response.setCharacterEncoding("UTF-8");
  30. response.getWriter().write(objectMapper.writeValueAsString(commonResult));
  31. response.getWriter().flush();
  32. response.getWriter().close();
  33. }
  34. }
登出成功:
  1. @Component
  2. public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
  3. private final ObjectMapper objectMapper;
  4. private final LogService logService;
  5. public MyLogoutSuccessHandler(ObjectMapper objectMapper, LogService logService) {
  6. this.objectMapper = objectMapper;
  7. this.logService = logService;
  8. }
  9. @Override
  10. public void onLogoutSuccess(
  11. HttpServletRequest request, HttpServletResponse response, Authentication authentication
  12. ) throws IOException, ServletException {
  13. String authHeader = request.getHeader(GlobalUtil.AUTHORIZATION);
  14. String authToken = authHeader.substring(GlobalUtil.GRANT_TYPE.length());
  15. String userJson = (String) LocalCache.getInstance().getValue(authToken);
  16. if (ObjectUtils.isEmpty(userJson)) {
  17. CommonResult commonResult = new CommonResult();
  18. commonResult.setCode(YIXGResultEnum.OPERATE_FAILURE.getCode())
  19. .setMessage(YIXGResultEnum.OPERATE_FAILURE.getMessage());
  20. response.setContentType("application/json;charset=UTF-8");
  21. response.getWriter().write(objectMapper.writeValueAsString(commonResult));
  22. response.getWriter().flush();
  23. response.getWriter().close();
  24. return;
  25. }
  26. MyUserDetail user = objectMapper.readValue(userJson, MyUserDetail.class);
  27. LocalCache.getInstance().putValue(authToken, "", 1);
  28. LogVO logVO = new LogVO();
  29. logVO.setLogOperateUser(user.getUserName())
  30. .setLogContent("登出成功")
  31. .setLogType("登录日志");
  32. logService.addLog(logVO);
  33. CommonResult commonResult = new CommonResult();
  34. commonResult.setCode(YIXGResultEnum.OPERATE_SUCCESS.getCode())
  35. .setMessage(YIXGResultEnum.OPERATE_SUCCESS.getMessage());
  36. response.setContentType("application/json;charset=UTF-8");
  37. response.getWriter().write(objectMapper.writeValueAsString(commonResult));
  38. response.getWriter().flush();
  39. response.getWriter().close();
  40. }
  41. }
Security核心配置:
  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityConfig {
  4. private final MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
  5. private final MyAuthenticationFailureHandler myAuthenticationFailureHandler;
  6. private final MyLogoutSuccessHandler myLogoutSuccessHandler;
  7. private final UserDetailsService userDetailsService;
  8. public SecurityConfig(
  9. MyAuthenticationSuccessHandler myAuthenticationSuccessHandler,
  10. MyAuthenticationFailureHandler myAuthenticationFailureHandler,
  11. MyLogoutSuccessHandler myLogoutSuccessHandler, UserDetailsService userDetailsService
  12. ) {
  13. this.myAuthenticationSuccessHandler = myAuthenticationSuccessHandler;
  14. this.myAuthenticationFailureHandler = myAuthenticationFailureHandler;
  15. this.myLogoutSuccessHandler = myLogoutSuccessHandler;
  16. this.userDetailsService = userDetailsService;
  17. }
  18. @Bean
  19. public AuthenticationManager authenticationManager(
  20. AuthenticationConfiguration authenticationConfiguration
  21. ) throws Exception {
  22. return authenticationConfiguration.getAuthenticationManager();
  23. }
  24. @Bean
  25. public PasswordEncoder passwordEncoder() {
  26. return new MyPasswordEncoder();
  27. }
  28. @Bean
  29. public MyAuthenticationTokenFilter myAuthenticationTokenFilter() {
  30. return new MyAuthenticationTokenFilter();
  31. }
  32. @Bean
  33. SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
  34. return httpSecurity
  35. // 禁用basic明文验证
  36. .httpBasic(Customizer.withDefaults())
  37. // 基于 token ,不需要 csrf
  38. .csrf(AbstractHttpConfigurer::disable)
  39. // 禁用默认登录页
  40. .formLogin(fl -> fl.loginProcessingUrl("/login")
  41. .usernameParameter("username")
  42. .passwordParameter("password")
  43. .successHandler(myAuthenticationSuccessHandler)
  44. .failureHandler(myAuthenticationFailureHandler)
  45. .permitAll())
  46. // 禁用默认登出页
  47. .logout(lt -> lt.logoutSuccessHandler(myLogoutSuccessHandler))
  48. // 基于 token , 不需要 session
  49. .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
  50. // 设置 处理鉴权失败、认证失败
  51. .exceptionHandling(
  52. exceptions -> exceptions.authenticationEntryPoint(new MyAuthenticationEntryPoint())
  53. .accessDeniedHandler(new MyAccessDeniedHandler())
  54. )
  55. // 下面开始设置权限
  56. .authorizeHttpRequests(authorizeHttpRequest -> authorizeHttpRequest
  57. // 允许所有 OPTIONS 请求
  58. .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
  59. // 允许直接访问 授权登录接口
  60. .requestMatchers(HttpMethod.POST, "/web/authenticate").permitAll()
  61. // 允许 SpringMVC 的默认错误地址匿名访问
  62. .requestMatchers("/error").permitAll()
  63. // 其他所有接口必须有Authority信息,Authority在登录成功后的UserDetailImpl对象中默认设置“ROLE_USER”
  64. //.requestMatchers("/**").hasAnyAuthority("ROLE_USER")
  65. .requestMatchers("/heartBeat/**", "/main/**").permitAll()
  66. // 允许任意请求被已登录用户访问,不检查Authority
  67. .anyRequest().authenticated()
  68. )
  69. // 添加过滤器
  70. .addFilterBefore(myAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class)
  71. .build();
  72. }
  73. @Bean
  74. public UserDetailsService userDetailsService() {
  75. return userDetailsService::loadUserByUsername;
  76. }
  77. /**
  78. * 调用loadUserByUserName获取userDetail信息,在AbstractUserDetailsAuthenticationProvider里执行用户状态检查
  79. *
  80. * @return
  81. */
  82. @Bean
  83. public AuthenticationProvider authenticationProvider() {
  84. DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
  85. authProvider.setUserDetailsService(userDetailsService);
  86. authProvider.setPasswordEncoder(passwordEncoder());
  87. return authProvider;
  88. }
  89. // @Bean
  90. // public WebSecurityCustomizer webSecurityCustomizer() {
  91. // return (web) -> web.ignoring().requestMatchers();
  92. // }
  93. /**
  94. * 配置跨源访问(CORS)
  95. *
  96. * @return
  97. */
  98. @Bean
  99. CorsConfigurationSource corsConfigurationSource() {
  100. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  101. source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
  102. return source;
  103. }
  104. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/519370
推荐阅读
相关标签
  

闽ICP备14008679号