Spring Security 学习笔记(二)

1.引入pom.xml文件

关键部分

        <!--security-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>5.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

补充部分

        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
		<!--转换成json字符串的工具-->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.2</version>
        </dependency>
        <!--commons-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

2.设置security的配置文件

SecurityConfig类 -> 配置类
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private UserService userService;
    /**
     * 未登录
     */
    @Resource
    private AuthenticationEntry authenticationEntry ;
    /**
     * 登录成功
     */
    @Resource
    private AuthenticationSuccess authenticationSuccess;
    /**
     * 登录失败
     */
    @Resource
    private AuthenticationFailure authenticationFailure;
    /**
     * 无权访问
     */
    @Resource
    private AccessDenied accessDenied ;
    /**
     * 注销操作
     */
    @Resource
    private LogoutSuccess logoutSuccess ;
    /**
     * 异地登录,账号下线时的逻辑处理
     */
    @Resource
    private SessionInformationExpiredStrategy sessionInformationExpiredStrategy;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userService)
                .passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //cors()解决跨域问题,csrf()会与restful风格冲突,默认 springsecurity 是开启的,所以要disable()关闭一下
        http.cors().and().csrf().disable();

        http.authorizeRequests()
                .antMatchers("/add").permitAll()
                .antMatchers("/test").hasRole("ADMIN")
                // hasRole会将参数自动加上ROLE_
                .and()
                //开启登录
                .formLogin()
                .usernameParameter("username")
                .passwordParameter("password")
                .loginPage("/toLogin")
                .loginProcessingUrl("/login")
                //允许所有人访问
                .permitAll()
                // 登录成功逻辑处理
                .successHandler(authenticationSuccess)
                // 登录失败逻辑处理
                .failureHandler(authenticationFailure)

                .and()
                //开启注销
                .logout()
                //允许所有人访问
                .permitAll()
                //注销逻辑处理
                .logoutSuccessHandler(logoutSuccess)
                //删除cookie
                .deleteCookies("JSESSIONID")

                .and().exceptionHandling()
                //权限不足的时候的逻辑处理
                .accessDeniedHandler(accessDenied)
                //未登录是的逻辑处理
                .authenticationEntryPoint(authenticationEntry)

                .and()
                .sessionManagement()
                //最多只能一个用户登录一个账号
                .maximumSessions(1)
                //异地登录,账号下线时的逻辑处理
                .expiredSessionStrategy(sessionInformationExpiredStrategy);

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }
}

AuthenticationEntry 类 -> 未登录时
/**
 * 未登录时
 * @author CH
 * @date 2021-08-19 15:23
 */
@Component
public class AuthenticationEntry implements AuthenticationEntryPoint {

    @Autowired
    Gson gson;

    /**
     * 未登录时返回给前端数据
     */
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, IOException {
        Result<Object> result = ResultUtil.error(401,"需要登录!!");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(gson.toJson(result));
    }
}

AuthenticationSuccess类 -> 登录成功时
/**
 * 登录成功后自定义操作
 * @author CH
 * @date 2021-08-19 16:23
 */
@Component
public class AuthenticationSuccess implements AuthenticationSuccessHandler {
    @Autowired
    Gson gson;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException, IOException {
        //登录成功时返回给前端的数据
        Result<Object> result = ResultUtil.success("登录成功!!!!!");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(gson.toJson(result));
    }
}

AuthenticationFailure类 -> 登录失败时
/**
 * 登录失败
 * @author CH
 * @date 2021-08-19 16:20
 */
@Component
public class AuthenticationFailure implements AuthenticationFailureHandler {
    @Autowired
    Gson gson;
    
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, IOException {
        Result<Object> result;
        if (e instanceof UsernameNotFoundException) {
            result = ResultUtil.error(-1,e.getMessage());
        } else if (e instanceof BadCredentialsException) {
            result = ResultUtil.error(-1,"密码错误!!");
        } else {
            result = ResultUtil.error(-1,e.getMessage());
        }
        //处理编码方式,防止中文乱码的情况
        response.setContentType("text/json;charset=utf-8");
        //返回给前台
        response.getWriter().write(gson.toJson(result));
    }
}
AccessDenied 类 -> 无权访问时
/**
 * 无权访问
 * @author CH
 * @date 2021-08-19 16:25
 */
@Component
public class AccessDenied implements AccessDeniedHandler {
    @Autowired
    Gson gson;

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException {
        Result<Object> result = ResultUtil.error(-1,"无权访问,need Authorities!!");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(gson.toJson(result));
    }
}

LogoutSuccess 类 ->注销操作时
/**
 * 注销操作
 * @author CH
 * @date 2021-08-19 17:12
 */
@Component
public class LogoutSuccess implements LogoutSuccessHandler {
    @Autowired
    Gson gson;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Result<Object> result = ResultUtil.success("注销成功");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(gson.toJson(result));
    }
}

SessionInformationExpiredStrategy类 ->异地登录时
/**
 * 异地登录,账号下线时的逻辑处理
 * @author CH
 * @date 2021-08-19 17:06
 */
@Component
public class SessionInformationExpiredStrategy implements org.springframework.security.web.session.SessionInformationExpiredStrategy {
    @Autowired
    Gson gson;

    @Override
    public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
        Result<Object> result = ResultUtil.error(-1,"您的账号在异地登录,建议修改密码");
        HttpServletResponse response = event.getResponse();
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(gson.toJson(result));
    }
}

3.项目其他设置

UserController
/**
 * @author CH
 * @date 2021-08-19 11:13
 */
@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/test")
    public String index(){
        return "首页---->"+LocalDateTime.now().toString();
    }

    @RequestMapping("/add")
    public String add() {
        User user = new User();
        user.setUsername("user1");
        user.setPassword("123456");
        user.setState(0);
        user.setRoleId(1);
        userService.add(user);
        return "添加用户---->"+LocalDateTime.now().toString();
    }

    @RequestMapping("ttt")
    public String ttt(){
        return "TTTT";
    }
}

UserService

需要继承UserDetailsService类

public interface UserService extends UserDetailsService {
    @Override
    UserDetails loadUserByUsername(String username);
    int add(User user);
}
UserServiceImpl
/**
 * @author CH
 * @date 2021-08-19 10:48
 */
@Service
public class UserServiceImpl implements UserService, UserDetailsService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) {
    	//自己写的查询
        UserDto userDto = userMapper.queryUserByUserName(username);
        if (username == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }

        List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
        String role = userDto.getCode();
        if (StringUtils.isNotBlank(role)) {
            authorityList.add(new SimpleGrantedAuthority(role.trim()));
        }
        //结尾返回org.springframework.security.core.userdetails.User!!
        return new org.springframework.security.core.userdetails
                .User(userDto.getUsername(), userDto.getPassword(), authorityList);
    }

    @Override
    public int add(User user) {
        user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
        return userMapper.add(user);
    }

}

UserMapper
@Mapper
public interface UserMapper {
	//自己写一下查询
    UserDto queryUserByUserName(String username);
    int add(User user);
}

application.yml
server:
  port: 8000
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/ch_pf?useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
  thymeleaf:
    prefix: classpath:/templates/
    cache: false
    suffix: .html
    mode: LEGACYHTML5
    template-resolver-order: 0
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  type-aliases-package: com.website.entity
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
    <form th:action="@{/login}" method="post">
      <input type="text" value="" name="username">
      <input type="password" value="" name="password">
      <input type="submit" value="提交">
    </form>
</body>
</html>

MVC配置
/**
 * MVC配置
 * @author CH
 * @date 2021-08-19 11:45
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/toLogin").setViewName("login");
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值