【Spring Security】

【Spring Security】
【Spring Security】
【Spring Security】

<dependencies>

    <dependency>

        <groupId>com.atguigu</groupId>

        <artifactId>common_utils</artifactId>

        <version>0.0.1-SNAPSHOT</version>

    </dependency>

    

    <!-- Spring Security依赖 -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-security</artifactId>

    </dependency>

    <dependency>

        <groupId>io.jsonwebtoken</groupId>

        <artifactId>jjwt</artifactId>

    </dependency>

</dependencies>

【Spring Security】
【Spring Security】
【Spring Security】


/**

 * <p>

 * Security配置类

 * </p>

 */

@Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true)

public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {


    private UserDetailsService userDetailsService;

    private TokenManager tokenManager;

    private DefaultPasswordEncoder defaultPasswordEncoder;
    private RedisTemplate redisTemplate;

    @Autowired
    public TokenWebSecurityConfig(UserDetailsService userDetailsService, DefaultPasswordEncoder defaultPasswordEncoder,

                                  TokenManager tokenManager, RedisTemplate redisTemplate) {

        this.userDetailsService = userDetailsService;

        this.defaultPasswordEncoder = defaultPasswordEncoder;

        this.tokenManager = tokenManager;

        this.redisTemplate = redisTemplate;

    }

    /**

     * 配置设置

     * @param http

     * @throws Exception

     */

    @Override

    protected void configure(HttpSecurity http) throws Exception {

        http.exceptionHandling()

                .authenticationEntryPoint(new UnauthorizedEntryPoint())

                .and().csrf().disable()

                .authorizeRequests()

                .anyRequest().authenticated()

                .and().logout().logoutUrl("/admin/acl/index/logout")

                .addLogoutHandler(new TokenLogoutHandler(tokenManager,redisTemplate)).and()

                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate))

                .addFilter(new TokenAuthenticationFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();

    }

    /**

     * 密码处理

     * @param auth

     * @throws Exception

     */

    @Override

    public void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(userDetailsService).passwordEncoder(defaultPasswordEncoder);

    }

    /**

     * 配置哪些请求不拦截

     * @param web

     * @throws Exception

     */

    @Override
    public void configure(WebSecurity web) throws Exception {

        web.ignoring().antMatchers("/api/**",

                "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"

               );

    }

}

【Spring Security】



import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;


/**

 * <p>

 * 密码的处理方法类型

 * </p>

 */

@Component
public class DefaultPasswordEncoder implements PasswordEncoder {

    public DefaultPasswordEncoder() {

        this(-1);

    }

    /**

    * @param strength

     *            the log rounds to use, between 4 and 
     */

    public DefaultPasswordEncoder(int strength) {

    }

    public String encode(CharSequence rawPassword) {

        return MD5.encrypt(rawPassword.toString());

    }

    public boolean matches(CharSequence rawPassword, String encodedPassword) {

        return encodedPassword.equals(MD5.encrypt(rawPassword.toString()));

    }

}

【Spring Security】

import io.jsonwebtoken.CompressionCodecs;

import io.jsonwebtoken.Jwts;

import io.jsonwebtoken.SignatureAlgorithm;

import org.springframework.stereotype.Component;


import java.util.Date;


/**

 * <p>

 * token管理

 * </p>

 */

@Component
public class TokenManager {


    private long tokenExpiration = 24*60*60*1000;

    private String tokenSignKey = "123456";

    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 String getUserFromToken(String token) {

        String user = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody().getSubject();

        return user;

    }

    public void removeToken(String token) {

        //jwttoken无需删除,客户端扔掉即可。

    }

}

【Spring Security】

/**

 * <p>

 * 登出业务逻辑类

 * </p>

 */

public class TokenLogoutHandler implements LogoutHandler {

    private TokenManager tokenManager;

    private RedisTemplate redisTemplate;

    public TokenLogoutHandler(TokenManager tokenManager, RedisTemplate redisTemplate) {

        this.tokenManager = tokenManager;

        this.redisTemplate = redisTemplate;

    }

    @Override

    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {

        String token = request.getHeader("token");

        if (token != null) {

            tokenManager.removeToken(token);

            //清空当前用户缓存中的权限数据

            String userName = tokenManager.getUserFromToken(token);

            redisTemplate.delete(userName);

        }

        ResponseUtil.out(response, R.ok());

    }

}

【Spring Security】

/**

 * <p>

 * 未授权的统一处理方式

 * </p>

 */

public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,

                         AuthenticationException authException) throws IOException, ServletException {

        ResponseUtil.out(response, R.error());

    }

}

【Spring Security】


/**

 * <p>

 * 安全认证用户详情信息

 * </p>

 */

@Data

@Slf4j

public class SecurityUser implements UserDetails {

    //当前登录用户

    private transient User currentUserInfo;

    //当前权限

    private List<String> permissionValueList;

    public SecurityUser() {

    }


    public SecurityUser(User user) {

        if (user != null) {

            this.currentUserInfo = user;

        }

    }

    @Override

    public Collection<? extends GrantedAuthority> getAuthorities() {

        Collection<GrantedAuthority> authorities = new ArrayList<>();

        for(String permissionValue : permissionValueList) {

            if(StringUtils.isEmpty(permissionValue)) continue;

            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);

            authorities.add(authority);

        }

        return authorities;

    }

    @Override

    public String getPassword() {

        return currentUserInfo.getPassword();

    }

    @Override

    public String getUsername() {

        return currentUserInfo.getUsername();

    }

    @Override
    public boolean isAccountNonExpired() {

        return true;

    }

    @Override
    public boolean isAccountNonLocked() {

        return true;

    }

    @Override
    public boolean isCredentialsNonExpired() {

        return true;

    }

    @Override

    public boolean isEnabled() {

        return true;

    }

}

【Spring Security】

/**

 * <p>

 * 用户实体类

 * </p>

 */

@Data

@ApiModel(description = "用户实体类")

public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "微信openid")

    private String username;

    @ApiModelProperty(value = "密码")

    private String password;

    @ApiModelProperty(value = "昵称")
    private String nickName;

    @ApiModelProperty(value = "用户头像")

    private String salt;

    @ApiModelProperty(value = "用户签名")

    private String token;

}

【Spring Security】

/**

 * <p>

 * 登录过滤器,继承UsernamePasswordAuthenticationFilter,对用户名密码进行登录校验

 * </p>

 */

public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    private TokenManager tokenManager;

    private RedisTemplate redisTemplate;

    public TokenLoginFilter(AuthenticationManager authenticationManager, TokenManager tokenManager, RedisTemplate redisTemplate) {

        this.authenticationManager = authenticationManager;

        this.tokenManager = tokenManager;

        this.redisTemplate = redisTemplate;

        this.setPostOnly(false);

        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/acl/login","POST"));

    }

    @Override

    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)

            throws AuthenticationException {

        try {

            User user = new ObjectMapper().readValue(req.getInputStream(), User.class);


            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));

        } catch (IOException e) {

            throw new RuntimeException(e);

        }


    }


    /**

     * 登录成功

     * @param req

     * @param res

     * @param chain

     * @param auth

     * @throws IOException

     * @throws ServletException

     */

    @Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,

                                            Authentication auth) throws IOException, ServletException {

        SecurityUser user = (SecurityUser) auth.getPrincipal();

        String token = tokenManager.createToken(user.getCurrentUserInfo().getUsername());

        redisTemplate.opsForValue().set(user.getCurrentUserInfo().getUsername(), user.getPermissionValueList());

        ResponseUtil.out(res, R.ok().data("token", token));

    }

    /**

     * 登录失败

     * @param request

     * @param response

     * @param e

     * @throws IOException

     * @throws ServletException

     */

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,

                                              AuthenticationException e) throws IOException, ServletException {

        ResponseUtil.out(response, R.error());

    }

}

【Spring Security】


/**

 * <p>

 * 访问过滤器

 * </p>

 */

public class TokenAuthenticationFilter extends BasicAuthenticationFilter {

    private TokenManager tokenManager;

    private RedisTemplate redisTemplate;


    public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager,RedisTemplate redisTemplate) {

        super(authManager);

        this.tokenManager = tokenManager;

        this.redisTemplate = redisTemplate;

    }


    @Override

    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)

            throws IOException, ServletException {

        logger.info("================="+req.getRequestURI());

        if(req.getRequestURI().indexOf("admin") == -1) {

            chain.doFilter(req, res);

            return;

        }


        UsernamePasswordAuthenticationToken authentication = null;

        try {

            authentication = getAuthentication(req);

        } catch (Exception e) {

            ResponseUtil.out(res, R.error());

        }

        if (authentication != null) {

            SecurityContextHolder.getContext().setAuthentication(authentication);

        } else {

            ResponseUtil.out(res, R.error());

        }

        chain.doFilter(req, res);

    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {

        // token置于header里

        String token = request.getHeader("token");

        if (token != null && !"".equals(token.trim())) {

            String userName = tokenManager.getUserFromToken(token);

            List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);

            Collection<GrantedAuthority> authorities = new ArrayList<>();

            for(String permissionValue : permissionValueList) {

                if(StringUtils.isEmpty(permissionValue)) continue;

                SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);

                authorities.add(authority);

            }

            if (!StringUtils.isEmpty(userName)) {

                return new UsernamePasswordAuthenticationToken(userName, token, authorities);

            }

            return null;

        }

        return null;

    }

}
上一篇:【Redis】WRONGTYPE Operation against a key holding the wrong kind of value


下一篇:HM-SpringBoot1.5【SpringBoot整合Redis】