springsecurity踩坑记录

1.搭建简单的springsecurity项目

参考文献:https://www.cnblogs.com/demingblog/p/10874753.html

第一步:引入security,jwt,fastjson的pom坐标

<!--springsecurity-->
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--jwt-->
<dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt</artifactId>
      <version>0.9.0</version>
</dependency>
<!--fastjson-->
<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.56</version>
</dependency>

第二步:创建一个controller

第三步:配置文件中配置用户名密码(不配置会有默认的用户名密码,默认的用户名是 user,密码则是一串 UUID 字符串,输出到了控制台日志里)

#springsecurity
spring.security.user.name=root
spring.security.user.password=root

第四步:启动项目,浏览器访问controller,会弹出登录框,用刚刚设置的用户名密码登录成功后会跳转到相应的controller,这种是HTTP Basic 认证的方式,接下来还有表单认证的方式。

2.自定义表单方式登陆

第一步:新建SecurityConfig类继承WebSecurityConfigurerAdapter,这个类主要是自定义安全方法,比如登陆方式,加密类型等

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //注入自定义的三个对象,下面附上该类代码
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private AuthenticationSuccessHandler successHandler;

    @Autowired
    private AuthenticationFailHandler failHandler;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
                .authorizeRequests();

        registry.and()
        //表单登录方式
                .formLogin()
                .permitAll()
        //成功处理类
                .successHandler(successHandler)
        //失败
                .failureHandler(failHandler)
                .and()
                .logout()
                .permitAll()
                .and()
                .authorizeRequests()
        //任何请求
                .anyRequest()
        //需要身份认证
                .authenticated()
                .and()
        //关闭跨站请求防护
                .csrf().disable()
        //前后端分离采用JWT 不需要session
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
    //自定义使用自己定义的userDetailsService,连接数据库,设置加密类型
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    //设置加密类型
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

第二步:新建CustomUserDetailsService类继承UserDetailsService,自定义登陆规则。

@Component("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //这个方法里可以调用通过username查询数据库的方法
        //User userFromDatabase = userRepository.findOneByLogin(login);
        //if (userFromDatabase == null) {
            //log.warn("User: {} not found", login);
            //throw new UsernameNotFoundException("User " + login + " was not found in db");
            //这里找不到必须抛异常
        //}
        //设置角色
        Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        //用加密方法给密码加密,注册的时候用
        //BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        //String encode = bCryptPasswordEncoder.encode("root");
        //这个密码是root加密后的密文,明文是root
        return new User("root",new BCryptPasswordEncoder().encode("root"),grantedAuthorities);
    }
}

第三步:新建AuthenticationSuccessHandler,登陆成功进入该方法

package com.wjn.security.handler;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.ResponseUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

@Slf4j
@Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {

        String username = ((UserDetails)authentication.getPrincipal()).getUsername();
        Collection<? extends GrantedAuthority> authorities = ((UserDetails) authentication.getPrincipal()).getAuthorities();
        List<String> list = new ArrayList<>();
        for(GrantedAuthority g : authorities){
            list.add(g.getAuthority());
        }
        //登陆成功生成token
        String  token = UUID.randomUUID().toString().replace("-", "");
        //token 需要保存至服务器一份,实现方式:redis or jwt输出到浏览器
        Map<Object, Object> map = new HashMap<>();
        map.put("code",200);
        map.put("msg","登陆成功");
        map.put("username",username);
        map.put("token",token);
        PrintWriter out = response.getWriter();
        response.setContentType("application/json; charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        Object o = JSONObject.toJSON(map);
        System.out.println(o);
        out.print(o.toString());
    }
}

第四步:新建AuthenticationFailHandler,登陆失败进入该方法

package com.wjn.security.handler;

import com.alibaba.fastjson.JSONObject;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@Component
public class AuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {

        // 默认情况下,不管你是用户名不存在,密码错误,SS 都会报出 Bad credentials 异常信息
        Map<Object, Object> map = new HashMap<>();
        if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) {
            map.put("code",500);
            map.put("msg","用户名或密码错误");
        } else if (e instanceof DisabledException) {
            map.put("code",500);
            map.put("msg","账户被禁用,请联系管理员");
        } else {
            map.put("code",500);
            map.put("msg","登录失败,其他内部错误");
        }
        PrintWriter out = response.getWriter();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        Object o = JSONObject.toJSON(map);
        out.print(o.toString());
    }

}

第五步:随便访问一个路径,进入登陆页面,然后输入正确的用户名密码或者错误的用户名密码会返回不同的json。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值