SpringSecurity

SecurityConfig配置

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final AdminDefineHandler defineHandler;

    private final UserDetailServiceImpl userDetailService;

    private final AdminLoginSuccessHandler successHandler;

    private final AdminLoginFailureHandler failureHandler;

    private final AdminLogoutSuccessHandler logoutSuccessHandle;

    private final AdminAuthenticationFilter adminAuthenticationFilter;

    private final AdminAuthenticationEntryPoint authenticationEntryPoint;

    private final AdminPasswordEncoder adminPasswordEncoder;

    public SecurityConfig(AdminDefineHandler defineHandler, UserDetailServiceImpl userDetailService, AdminLoginSuccessHandler successHandler, AdminLoginFailureHandler failureHandler, AdminLogoutSuccessHandler logoutSuccessHandle, AdminAuthenticationFilter adminAuthenticationFilter, AdminAuthenticationEntryPoint authenticationEntryPoint, AdminPasswordEncoder adminPasswordEncoder) {
        this.defineHandler = defineHandler;
        this.userDetailService = userDetailService;
        this.successHandler = successHandler;
        this.failureHandler = failureHandler;
        this.logoutSuccessHandle = logoutSuccessHandle;
        this.adminAuthenticationFilter = adminAuthenticationFilter;
        this.authenticationEntryPoint = authenticationEntryPoint;
        this.adminPasswordEncoder = adminPasswordEncoder;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailService)
                .passwordEncoder(adminPasswordEncoder);
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests()
                .antMatchers("/sso/login","/swagger-resources/**","/webjars/**","/v2/**","/swagger-ui.html/**").permitAll()
                .anyRequest().authenticated()
                .and().formLogin().loginProcessingUrl("/sso/login")
                .usernameParameter("username").passwordParameter("password")
                .successHandler(successHandler)
                .failureHandler(failureHandler).and()
                .logout().logoutUrl("/sso/logout").clearAuthentication(true).invalidateHttpSession(true)
                .logoutSuccessHandler(logoutSuccessHandle)
                .and().addFilterBefore(adminAuthenticationFilter, BasicAuthenticationFilter.class)
                .cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(defineHandler);
    }

    @Override
    public void configure(WebSecurity web){
        web.ignoring().antMatchers("/v2/api-docs",
                "/swagger-resources/configuration/ui",
                "/swagger-resources",
                "/swagger-resources/configuration/security",
                "/swagger-ui.html");
    }

实现UserDetailsService接口

@Service("userDetailService")
@Slf4j
public class UserDetailServiceImpl implements UserDetailsService {

    private final SysUserMapper userMapper;

    private final RouteService routeService;

    private final SysUserRoleMapper userRoleMapper;

    private final SysRoleMapper roleMapper;

    private final SysRouteMapper routeMapper;

    private final SysRoleRouteMapper roleRouteMapper;

    public UserDetailServiceImpl(SysUserMapper userMapper, RouteService routeService, SysUserRoleMapper userRoleMapper, SysRoleMapper roleMapper, SysRouteMapper routeMapper, SysRoleRouteMapper roleRouteMapper, SysDepartmentMapper departmentMapper) {
        this.userMapper = userMapper;
        this.routeService = routeService;
        this.userRoleMapper = userRoleMapper;
        this.roleMapper = roleMapper;
        this.routeMapper = routeMapper;
        this.roleRouteMapper = roleRouteMapper;
        this.departmentMapper = departmentMapper;
    }


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username",username).eq("enable", CommonConst.NORMAL_STATE);
        List<SysUser> userList = userMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(userList)){
            throw new UsernameNotFoundException("用户不存在");
        }
        SysUser sysUser = userList.get(0);
        SecurityUser securityUser = new SecurityUser();
        securityUser.setId(sysUser.getId());
        securityUser.setUsername(sysUser.getUsername());
        securityUser.setState(sysUser.getState());
        securityUser.setPassword(sysUser.getPassword());
        securityUser.setRoleList(getRoleList(sysUser.getId()));
        securityUser.setRouteList(getRouteList(sysUser.getId()));
        securityUser.setAuthorities(setAuthorityList(sysUser.getId()));
        return securityUser;
    }

    /**
     * 添加权限集合
     * @param id 用户ID
     * @return 权限集合
     */
    private Collection<? extends GrantedAuthority> setAuthorityList(Long id) {
        List<SysRoute> routeList = getRouteListByUserId(id);
        Collection<GrantedAuthority> authorities = new HashSet<>();
        if (!CollectionUtils.isEmpty(routeList)){
            List<SysRoute> sysRoutes = routeList.stream().filter(route -> Objects.equals(route.getRouteType(), SysConst.ROUTE_PERMISSION))
                    .collect(Collectors.toList());
            for (SysRoute sysRoute : sysRoutes) {
                SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(sysRoute.getPermission());
                authorities.add(simpleGrantedAuthority);
            }
        }
        return authorities;
    }

    /**
     * 获取用户下所有的路由列表
     * @param id 用户ID
     * @return 路由列表
     */
    private List<SysRoute> getRouteListByUserId(Long id) {
        List<SysRoleVO> roleList = getRoleList(id);
        if (CollectionUtils.isEmpty(roleList)){
            return Collections.emptyList();
        }
        List<Long> roleIds = roleList.stream().map(SysRoleVO::getId).collect(Collectors.toList());
        QueryWrapper<SysRoleRoute> wrapper = new QueryWrapper<>();
        wrapper.in("role_id",roleIds);
        List<SysRoleRoute> sysRoleRoutes = roleRouteMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(sysRoleRoutes)){
            return Collections.emptyList();
        }
        List<Long> routeIds = sysRoleRoutes.stream().map(SysRoleRoute::getRouteId).distinct().collect(Collectors.toList());
        return routeMapper.selectBatchIds(routeIds);
    }

    /**
     * 查询路由信息
     * @param id 用户信息
     * @return 路由列表
     */
    private List<SysRouteVO> getRouteList(Long id) {
       return routeService.getUserRouteList(id);
    }

    /**
     * 添加角色信息
     * @param id 用户ID
     * @return 角色列表
     */
    private List<SysRoleVO> getRoleList(Long id) {
        QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",id);
        List<SysUserRole> userRoles = userRoleMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(userRoles)){
            return Collections.emptyList();
        }
        List<Long> roleIdList = userRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        List<SysRole> sysRoles = roleMapper.selectBatchIds(roleIdList);
        return sysRoles.stream().map(role -> {
            SysRoleVO sysRoleVO = new SysRoleVO();
            BeanUtils.copyProperties(role,sysRoleVO);
            return sysRoleVO;
        }).collect(Collectors.toList());
    }

SecurityUser类

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties({"enabled","accountNonExpired", "accountNonLocked", "credentialsNonExpired"})
public class SecurityUser implements UserDetails {

    /**
     * 用户ID
     */
    private Long id;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 账号禁用状态 0:启用 1 :禁用
     */
    private Byte state;

    /**
     * 角色集合
     */
    private List<SysRoleVO> roleList;

    /**
     * 导航栏集合
     */
    private List<SysRouteVO> routeList;

    /**
     * token令牌
     */
    private String authorization;

    /**
     * 权限集合
     */
    @JsonDeserialize(using = AdminDeserializerUtils.class)
    private Collection<? extends GrantedAuthority> authorities;


    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return Objects.equals(state, SysConst.USER_ENABLE_STATE);
    }
}

SecurityUser转json需要序列化

public class AdminDeserializerUtils extends JsonDeserializer<List<GrantedAuthority>> {

    @Override
    public List<GrantedAuthority> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec();
        JsonNode jsonNode = mapper.readTree(jsonParser);
        List<GrantedAuthority> grantedAuthorities = new LinkedList<>();
        Iterator<JsonNode> elements = jsonNode.elements();
        while (elements.hasNext()){
            JsonNode next = elements.next();
            JsonNode authority = next.get("authority");
            grantedAuthorities.add(new SimpleGrantedAuthority(authority.asText()));

        }
        return grantedAuthorities;
    }
}

每次请求接口前需要认证

@Component
@Slf4j
public class AdminAuthenticationFilter extends OncePerRequestFilter {

    private final StringRedisTemplate stringRedisTemplate;

    public AdminAuthenticationFilter(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        if (StringUtils.isBlank(token)) {
            filterChain.doFilter(request, response);
            return;
        }
        UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        filterChain.doFilter(request, response);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) throws JsonProcessingException {
        String token = request.getHeader("Authorization");
        String securityStr = stringRedisTemplate.opsForValue().get(RedisKeyConst.LOGIN_KEY + "::" + token);
        if (securityStr != null){
            ObjectMapper objectMapper = new ObjectMapper();
            SecurityUser securityUser = objectMapper.readValue(securityStr, SecurityUser.class);
            SecurityUserUtils.setSecurityUser(securityUser);
            return new UsernamePasswordAuthenticationToken(securityUser.getUsername(),null,securityUser.getAuthorities());
        }
        return null;
    }

}

接口认证失败

@Component
public class AdminAuthenticationEntryPoint implements AuthenticationEntryPoint {


    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
        httpServletResponse.setContentType("application/json;charset=utf-8");
        PrintWriter out = httpServletResponse.getWriter();
        httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        Map<String, Object> map = new HashMap<>(5);
        map.put("errCode", HttpServletResponse.SC_UNAUTHORIZED);
        map.put("msg", "认证失败");
        map.put("data",null);
        ObjectMapper om = new ObjectMapper();
        out.write(om.writeValueAsString(map));
        out.flush();
        out.close();
    }
}

权限不足

@Component
public class AdminDefineHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException{
        httpServletResponse.setContentType("application/json;charset=utf-8");
        PrintWriter out = httpServletResponse.getWriter();
        httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
        Map<String, Object> map = new HashMap<>(5);
        map.put("errCode", HttpServletResponse.SC_FORBIDDEN);
        map.put("msg", "权限不足");
        map.put("data",null);
        ObjectMapper om = new ObjectMapper();
        out.write(om.writeValueAsString(map));
        out.flush();
        out.close();
    }
}

登录失败

@Component
public class AdminLoginFailureHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException{
        httpServletResponse.setContentType("application/json;charset=utf-8");
        PrintWriter out = httpServletResponse.getWriter();
        httpServletResponse.setStatus(HttpStatus.HTTP_UNAUTHORIZED);
        Map<String, Object> map = new HashMap<>(5);
        if (e instanceof BadCredentialsException){
            map.put("errCode", ResultCodeEnum.ACCOUNT_ERROR.getCode());
            map.put("msg", ResultCodeEnum.ACCOUNT_ERROR.getMsg());
        } else if (e instanceof DisabledException){
            map.put("errCode", ResultCodeEnum.ACCOUNT_LOCK.getCode());
            map.put("msg", ResultCodeEnum.ACCOUNT_LOCK.getMsg());
        }else {
            map.put("errCode", ResultCodeEnum.SYSTEM_ERROR.getCode());
            map.put("msg", ResultCodeEnum.SYSTEM_ERROR.getMsg());
        }
        map.put("data",null);
        ObjectMapper mapper = new ObjectMapper();
        out.write(mapper.writeValueAsString(map));
        out.flush();
        out.close();
    }
}

登录成功

@Component
public class AdminLoginSuccessHandler implements AuthenticationSuccessHandler {

    private final StringRedisTemplate stringRedisTemplate;

    public AdminLoginSuccessHandler(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication auth) throws IOException {
        SecurityUser securityUser = (SecurityUser) auth.getPrincipal();
        securityUser.setPassword(null);
        httpServletResponse.setContentType("application/json;charset=utf-8");
        setAuthorization(securityUser);

        //隐藏内部信息
        securityUser.setDepartmentIdList(Collections.emptyList());
        securityUser.setWbsList(Collections.emptyList());
        securityUser.setRoleList(Collections.emptyList());

        PrintWriter out = httpServletResponse.getWriter();
        httpServletResponse.setStatus(HttpServletResponse.SC_OK);
        Map<String, Object> map = new HashMap<>(5);
        map.put("errCode", ErrCode.SUCCESS);
        map.put("msg", "登录成功");
        map.put("data",securityUser);
        ObjectMapper om = new ObjectMapper();
        out.write(om.writeValueAsString(map));
        out.flush();
        out.close();
    }

    private void setAuthorization(SecurityUser securityUser) throws JsonProcessingException {
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        securityUser.setAuthorization(token);
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonStr = objectMapper.writeValueAsString(securityUser);
        stringRedisTemplate.opsForValue().set(RedisKeyConst.LOGIN_KEY +"::"+token,jsonStr,4, TimeUnit.HOURS);
    }
}

退出登录

@Component
public class AdminLogoutSuccessHandler implements LogoutSuccessHandler {

    private final StringRedisTemplate stringRedisTemplate;

    public AdminLogoutSuccessHandler(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException{
        String authorization = httpServletRequest.getHeader("Authorization");
        stringRedisTemplate.delete(RedisKeyConst.LOGIN_KEY +"::"+authorization);

        SecurityUserUtils.removeSecurityUser();
        httpServletResponse.setContentType("application/json;charset=utf-8");
        PrintWriter out = httpServletResponse.getWriter();
        httpServletResponse.setStatus(HttpStatus.HTTP_OK);
        Map<String, Object> map = new HashMap<>(5);
        map.put("errCode", ErrCode.SUCCESS);
        map.put("msg", "退出成功");
        map.put("data",null);
        ObjectMapper om = new ObjectMapper();
        out.write(om.writeValueAsString(map));
        out.flush();
        out.close();
    }
}

自定义密码加密解密

@Component
public class AdminPasswordEncoder implements PasswordEncoder {

    /**
     * 对密码加密返回
     * @param charSequence 未加密字符串
     * @return 加密后的字符串
     */
    @SneakyThrows
    @Override
    public String encode(CharSequence charSequence) {
        String str = charSequence.toString();
        return AesSecurityUtils.encrypt(AesSecurityUtils.AES_KEY,str);
    }

    /**
     * 验证密码是否正确
     * @param charSequence 未加密字符串
     * @param encodedPassword 加密后字符串
     * @return 两个字符串是否相等
     */
    @SneakyThrows
    @Override
    public boolean matches(CharSequence charSequence, String encodedPassword) {
        String str = charSequence.toString();
        String decrypt = AesSecurityUtils.decrypt(AesSecurityUtils.AES_KEY, encodedPassword);
        return str.equals(decrypt);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值