springsecurity复习

springsecurity

新建springboot项目

1.导入依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>


    </dependencies>

2.application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/textnode?serverTimeZone=UTC&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

3. entity层

//和数据库字段一样
@Data
@TableName("tian")
public class UserLogin {
    @TableId(type = IdType.AUTO)
    private int id;

    private String name;

    private String password;
}

4.dao层

@Mapper
@Repository
public interface UserMapper extends BaseMapper<UserLogin> {
}

5.service层

public interface UserService extends IService<UserLogin> {
}



@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserLogin> implements UserService {
}

6.controller层

package com.example.springsecuritydemo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class LoginController {
//    @RequestMapping("/login")
//    public String login(){
//        return "redirect:main.html";
//    }

    @RequestMapping("/toMain")
    public String toMain(){
        return "redirect:main.html";
    }

    @RequestMapping("/toError")
    public String toError(){
        return "redirect:error.html";
    }
}

config

package com.example.springsecuritydemo.config;

import com.example.springsecuritydemo.handle.MyAuthenticationFailHandle;
import com.example.springsecuritydemo.handle.MyAuthenticationSuccessHandle;
import com.example.springsecuritydemo.service.UserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailServiceImpl userDetailService;
/*
    // 没有加此段代码 数据库密码如果是明文,UserDetailServiceImpl传入的明文密码登录不进去,加了就可以或者 UserDetailServiceImpl传入的密码是经过加密返回User对象就可以登录成功
    
   @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailService).passwordEncoder(getPw()); //注释掉原本从内存中加载用户的代码。 }
    }
*/
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
//         .usernameParameter("username123")//自定义入参和前端的name属性一样
//         .passwordParameter("password123")//自定义入参
                .loginPage("/login.html") //自定义登录页面
                .loginProcessingUrl("/login")//必须和表单提交的接口一样,回去执行自定义登录逻辑
//        .successForwardUrl("/toMain")//登录成功后跳转的页面 POST请求
                //前后端分离 跳转不归我们管 编写handle.MyAuthenticationSuccessHandle
                .successHandler(new MyAuthenticationSuccessHandle("http://www.baidu.com"))
//        .failureForwardUrl("/toError") //登录失败后跳转的页面 POST请求
                .failureHandler(new MyAuthenticationFailHandle("/error.html"))//自定义登陆失败处理器
        ;

        //授权
        http.authorizeRequests()
            	//放行 不用登录
                .antMatchers("/login.html").permitAll()
            //放行 不用登录
                .antMatchers("/error.html").permitAll()
                //拦截所有请求
                .anyRequest().authenticated();

        //防止网站攻击
        http.csrf().disable();//登录失败可能存在的原因

    }

    @Bean
    public PasswordEncoder getPw() {
        return new BCryptPasswordEncoder();
    }

}

UserDetailServiceImpl

package com.example.springsecuritydemo.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.springsecuritydemo.entity.UserLogin;
import com.example.springsecuritydemo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.*;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class UserDetailServiceImpl implements UserDetailsService{
//    @Autowired
//    UserService service;
    @Autowired
    UserMapper mapper;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<UserLogin> wrapper = new QueryWrapper<>();
wrapper.eq("name",username);
        UserLogin one = mapper.selectOne(wrapper);
        if(one==null){
            throw new UsernameNotFoundException("用户名不存在");

        }
//        String password = passwordEncoder.encode(one.getPassword()); //加密后传入
//        System.out.println(password);
        return new User(username,one.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));

    }

}

handle/MyAuthenticationFailHandle

package com.example.springsecuritydemo.handle;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyAuthenticationFailHandle implements AuthenticationFailureHandler {
    private String url;

    public MyAuthenticationFailHandle(String url) {
        this.url = url;
    }


    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.sendRedirect(url);
    }
}

handle/MyAuthenticationSuccessHandle

package com.example.springsecuritydemo.handle;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyAuthenticationSuccessHandle implements AuthenticationSuccessHandler {
    private String url;

    public MyAuthenticationSuccessHandle(String url) {
        this.url = url;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.sendRedirect(url);

    }
}

前端static/login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
<!--   注意name属性必须是 username  可以后端改-->
    用户名 : <input type="text" name="username">
    <!--   注意name属性必须是 password   -->
    密码 : <input type="password" name="password">
    <input type="submit" value="登录">
</form>
</body>
</html>

error.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登陆失败
<a href="/login.html">跳到登陆页面</a>
</body>
</html>

main.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登录成功
</body>
</html>

授权

anyRequest()

注意要放在最后面 是按顺序的 ,放最前面其他放行的请求都会被拦截

     //授权
        http.authorizeRequests()
            	//放行 不用登录
                .antMatchers("/login.html").permitAll()
            //放行 不用登录
                .antMatchers("/error.html").permitAll()
                //拦截所有请求
                .anyRequest().authenticated();

antMatchers()

放行 静态资源

? 匹配一个字符
* 匹配0个或多个字符
** 匹配0个或多个目录
    
//例
.antMatchers("/css/**","/js/**","/images/**").permitAll()
.antMatchers("/**/*.png").permitAll()

regexMatchers()

//正则匹配
.regexMatchers(".+[.]png").permitAll()
//还有一个参数控制请求方法的 必须post才放行
.regexMatchers(HttpMethod.POST,"/demo").permitAll()

mvcMatchers()

//整个项目加前缀访问路径
//只在mvcMatchers里面有servletPath方法
.mvcMatchers("/demo").servletPath("/xxxx").permitAll()
    等价于
.antMatchers("/xxxx/demo").permitAll()  

控制的permitAll()还有其他的控制方法

在这里插入图片描述

基于权限判断

//严格区分大小写
.antMatchers("/main1.html").hasAuthority("admin").permitAll()
    
    
//只要有一个权限就可以访问
 .antMatchers("/main1.html").hasAnyAuthority("admin","admiN").permitAll()   

基于角色判断

    //给用户加角色 必须是 ROLE_ 开头
   return new User(username,one.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal,ROLE_abc"));

//严格区分大小写
.antMatchers("/main1.html").hasRole("abc").permitAll()
    
    
//只要有一个角色就可以访问
 .antMatchers("/main1.html").hasAnyRole("abc","ABC").permitAll()

基于ip判断

.antMatchers("/main1.html").hasIpAddress("127.0.0.1").permitAll()

自定义403处理方案

定义配置类

在这里插入图片描述

使用

在这里插入图片描述

基于Access的访问控制

  • 前面的控制方法都是基于Access
//写法
.antMatchers("/main1.html").access("permitAll")
    
.antMatchers("/main1.html").access("hasRole('admin')")

自定义Access方法

编写接口及其实现类

在这里插入图片描述

使用

在这里插入图片描述

启动访问main.html 报错 没有 跳转的路径 的权限

添加访问权限

在这里插入图片描述

启动访问 成功~

用户授权的注解使用

@Secured

表示用户具有某个角色,可以访问方法

1.启动类开启注解

在这里插入图片描述

2.使用

  • 区分大小写

在这里插入图片描述

@PreAuthorize

在进入方法之前做验证,看是否有权限进入

区分大小写 可以 加前缀ROLE_

在这里插入图片描述

@PostAuthorize

方法执行之后校验 没什么大用

RememberMe

1.导入依赖

基于springjdbc的 但springjdbc很少用 用mybatis+mysql

2.编写mysql连接配置

3.使用 配置类增加配置
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.前端加上记住我

在这里插入图片描述

thymeleaf中spring security的使用

1.导入依赖

在这里插入图片描述

2.前端页面

在这里插入图片描述

3.现象

在这里插入图片描述

设置用户角色和权限

在这里插入图片描述

退出登录

直接在前端写上退出链接
<a href="/logout">退出</a>

但地址栏会有lougout,不想看见怎么办?
配置类配置
//退出
http.logout() 
    //自定义退出  前端的退出请求也得是这个  最好就用默认的
    //.logoutUrl("/user/logout")
    .logoutUrl("/logout")
    //退出成功后跳转的页面
    .logoutSuccessUrl("/login.html")

CRSF

跨站请求伪造

跨域: 网络协议 ip地址 端口中任何一个不相同就是跨域请求

在这里插入图片描述

此时就登陆不成功

解决

在这里插入图片描述

Oauth2认证

在这里插入图片描述

第三方认证技术方案最主要是解决认证协议的通用标准问题,因为要实现跨系统认证,各系统之间要遵循一定的接口协议。

在这里插入图片描述

环境搭建

1.新建springboot工程

2.导入依赖 注意springboot版本

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.11.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.tian</groupId>
    <artifactId>springsecurityoauth2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springsecurityoauth2</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3.pojo/user

package com.tian.springsecurityoauth2.pojo;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;

public class User implements UserDetails {
    private String username;
    private String password;
    private List<GrantedAuthority> authorities;

    public User(String username, String password, List<GrantedAuthority> authorities) {
        this.username = username;
        this.password = password;
        this.authorities = authorities;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

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

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

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

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

4.service/UserService

package com.tian.springsecurityoauth2.service;

import com.tian.springsecurityoauth2.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class UserService implements UserDetailsService {
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String password = passwordEncoder.encode("123456");

        return new User(username,password,AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

5.controller/UserController

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/getCurrent")
    public Object getCurrent(Authentication authentication){
        return authentication.getPrincipal();
    }
}

6.config/SecurityConfig

package com.tian.springsecurityoauth2.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/oauth/**","/login/**",
                        "/logout/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll()
                .and()
                .csrf().disable();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

7.config/AuthorzationServerConfig

package com.tian.springsecurityoauth2.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;

@Configuration
@EnableAuthorizationServer
public class AuthorzationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                //客户端ID
                .withClient("client")
                //密钥
                .secret(passwordEncoder.encode("112233"))
                //重定向地址
                .redirectUris("http://www.baidu.com")
                //授权范围
                .scopes("all")
                //授权类型 - authorization_code 授权码模式
                .authorizedGrantTypes("authorization_code");
    }
}

8.config/ResourceServerConfig

package com.tian.springsecurityoauth2.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
               .anyRequest()
                .authenticated()
                .and().requestMatchers()
                .antMatchers("/user/**")
        ;
    }
}

启动访问

http://localhost:8080/oauth/authorize?response_type=code&client_id=client&redirect_uri=http://www.baidu.com&scope=all

返回到springsecurity自定义的登录页面

输入 admin 123456 跳到这个页面 点击允许 跳转到百度

在这里插入图片描述

注意百度地址栏有个授权码

在这里插入图片描述

拿着返回的token请求资源

在这里插入图片描述

实际上token不会存在内存,我们这边用redis存储

redis存储token

1.添加依赖

2.配置文件

在这里插入图片描述

3.配置类

在这里插入图片描述

4.使用

在这里插入图片描述

在这里插入图片描述

JWT

是一个标准

JJWT

是JWT的实现

1.创建springboot项目

2.导入依赖

在这里插入图片描述

3.启动类

4.测试

在这里插入图片描述

5.现象

在这里插入图片描述

解析token

在这里插入图片描述

现象

在这里插入图片描述

JWT过期校验

在这里插入图片描述

自定义claims

在这里插入图片描述

获取

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值