springsecurity配置及使用

学习时是看b站狂神说java讲解的springsecurity发现WebSecurityConfigurerAdapter类已经被弃用(2.7.0以下版本可继续使用,2.7.0以上已被启用),于是看官方文档写的一个新版本的配置,新旧对比学习

1.pom依赖
<!--        security-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
1.用户认证和授权

旧版本

@EnableWebSecurity
public class Security extends WebSecurityConfigurerAdapter {


    /**
     * 授权
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests()
            //首页所有人可以访问,功能也特定人访问
            //请求授权的规则
            .antMatchers("/").permitAll()
            .antMatchers("/level1/**").hasRole("vip1")
            .antMatchers("/level2/**").hasRole("vip2")
            .antMatchers("/level3/**").hasRole("vip3")
            .and()
            //无权限默认跳转登录页
            .formLogin()
            .and()
            .build();
			 //注销,开启注销功能跳转到首页
        http
            .logout().logoutSuccessUrl("/");
    }

    /**
     * 认证
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("lzx")
                .password("123456")
                .roles("vip1", "vip2")
                .and()
                .withUser("root")
                .password("123456")
                .roles("vip1", "vip2", "vip3");
    }
}

新版本

@EnableWebSecurity
public class SecurityConfig{

    /**
     * 授权
     * @param http
     * @return
     * @throws Exception
     */
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        //首页所有人可以访问,功能也特定人访问
        //请求授权的规则
        return http
                .authorizeHttpRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3")
                .and()
                //无权限默认跳转登录页
                .formLogin()
                .and()
                //注销,开启注销功能,跳转到首页
                .logout().logoutSuccessUrl("/")
                .and()
                .build();
    }

    /**
     * withDefaultPasswordEncoder 被遗弃,原因是不安全,只能在例子中使用
     * 不加密码编码使用时会报错    启动时不会报错  passwordEncoder
     * 认证例子
     * @return
     */
    @Bean
    public UserDetailsService users() {
        //密码加密
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        //设置用户
        UserDetails user = User.builder()
                .username("lzx")
                .password(encoder.encode("123456"))
                //用户权限
                .roles("vip1", "vip2")
                .build();
        UserDetails admin = User.builder()
                .username("root")
                .password(encoder.encode("123456"))
                .roles("vip1", "vip2", "vip3")
                .build();
        return new InMemoryUserDetailsManager(user, admin);
    }


}
2.与thymeleaf集成
2.1pom依赖
<!--        thymeleaf模板-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>

        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>

			<!--        thymeleaf集成springsecurity-->
			<dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        </dependency>
2.2html页面使用
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
>
2.3sec的使用
2.3.1语法格式
<!--如果未登录-->
<!-- isAuthenticated()判断用户是否登录 -->
<!-- 使用格式 sec:authorize="选择方法" -->
<div sec:authorize="!isAuthenticated()">
     <a class="item" th:href="@{/toLogin}">
         <i class="address card icon"></i> 登录
     </a>
 </div>
2.3.2登录账号名称
获取登录用户的名称
用户名:<span sec:authentication="name"></span>&nbsp;&nbsp;
2.3.3principal登录主体(例如我们在配置中设置的lzx与root两个用户的所有信息)
 用户名:<span sec:authentication="principal.username"></span>&nbsp;&nbsp;
 角色:<span sec:authentication="principal.authorities"></span>
2.3.4权限判断
 <div class="column" sec:authorize="hasRole('vip1')">
 			有vip1权限时显示
 </div>

基于数据库的权限配置

在之前的配置中我们设置用户使用的是
 @Bean
    public UserDetailsService users() {
        //密码加密
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        //设置用户
        UserDetails user = User.builder()
                .username("lzx")
                .password(encoder.encode("123456"))
                //用户权限
                .roles("vip1", "vip2")
                .build();
        UserDetails admin = User.builder()
                .username("root")
                .password(encoder.encode("123456"))
                .roles("vip1", "vip2", "vip3")
                .build();
        return new InMemoryUserDetailsManager(user, admin);
    }
如果要将数据库拉进来就不能这样使用了,使用步骤如下
注释掉原来的配置
//    @Bean
//    public UserDetailsService users() {
//
//
//        //密码加密
//        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
//        //设置用户
//        UserDetails user = User.builder()
//                .username("lzx")
//                .password(encoder.encode("123456"))
//                //用户权限
//                .roles("vip1", "vip2")
//                .build();
//        UserDetails admin = User.builder()
//                .username("root")
//                .password(encoder.encode("123456"))
//                .roles("vip1", "vip2", "vip3")
//                .build();
//        return new InMemoryUserDetailsManager(user, admin);
//    }
定义一个类实现UserDetails接口(用户登录存放的个人信息)必须有用户名密码,需要进行密码比对,权限属性也在这个类中
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Collection;

/**
 * @author 又菜又爱玩
 * @version 1.0
 * @date 2022/9/5 9:59
 * @blog https://blog.csdn.net/biancheng4/article/details/121727982
 */

@Component
public class AuthUser implements UserDetails {

    private String username;

    private String password;

    private String station;

    private Collection<? extends GrantedAuthority> authorities;

    public AuthUser() {
    }

    public AuthUser(String username, String password, String station, Collection<? extends GrantedAuthority> authorities) {
        this.username = username;
        this.password = password;
        this.station = station;
        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;
    }

    public String getStation() {
        return station;
    }

    public void setStation(String station) {
        this.station = station;
    }

    @Override
    public String toString() {
        return "AuthUser{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", station='" + station + '\'' +
                ", authorities=" + authorities +
                '}';
    }
}

实现UserDetailsService方法(自定义逻辑控制认证逻辑)
import com.lzx.springbootsecurity.pojo.security.AuthUser;
import com.lzx.springbootsecurity.pojo.user.Permission;
import com.lzx.springbootsecurity.pojo.user.Role;
import com.lzx.springbootsecurity.pojo.user.User;
import com.lzx.springbootsecurity.service.user.UserService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author 又菜又爱玩
 * @version 1.0
 * @date 2022/9/5 10:05
 * @blog https://blog.csdn.net/biancheng4/article/details/121727982
 */

@Component
public class UserDetailServiceImpl implements UserDetailsService {

    @Resource
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("username:"+username);
        if (username == null){
            return null;
        }
        User userByUsername = userService.findUserByUsername(username);
        System.out.println("user:" + userByUsername.toString());
        List<GrantedAuthority> list = new ArrayList<>();
        Set<Role> roles = userByUsername.getRoles();

        for (Role role : roles) {
            list.add(new SimpleGrantedAuthority(role.getKeyword()));
            Set<Permission> permissionSet = role.getPermissionSet();
            for (Permission permission : permissionSet) {
                list.add(new SimpleGrantedAuthority(permission.getKeyword()));
            }
        }

        return new AuthUser(username, userByUsername.getPassword(), userByUsername.getStation(), list);
    }
}

UserService类实现的主要是去数据库查询用户信息,角色,权限并组合起来
import com.lzx.springbootsecurity.mapper.user.PermissionMapper;
import com.lzx.springbootsecurity.mapper.user.RoleMapper;
import com.lzx.springbootsecurity.mapper.user.UserMapper;
import com.lzx.springbootsecurity.pojo.user.Permission;
import com.lzx.springbootsecurity.pojo.user.Role;
import com.lzx.springbootsecurity.pojo.user.User;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Set;

/**
 * @author 又菜又爱玩
 * @version 1.0
 * @date 2022/9/5 10:28
 * @blog https://blog.csdn.net/biancheng4/article/details/121727982
 */

@Service
public class UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private PermissionMapper permissionMapper;

    public User findUserByUsername(String username){
        User byUserName = userMapper.findByUserName(username);
        if (byUserName == null){
            return null;
        }
        Integer userId = byUserName.getId();
        Set<Role> byUserId = roleMapper.findByUserId(userId);
        for (Role role : byUserId) {
            Set<Permission> byRoleId = permissionMapper.findByRoleId(role.getId());
            role.setPermissionSet(byRoleId);
        }
        byUserName.setRoles(byUserId);
        return byUserName;
    }
}

用户类
import com.fasterxml.jackson.annotation.JsonIgnore;

import java.util.Date;
import java.util.Set;

/**
 * @author 又菜又爱玩
 * @version 1.0
 * @date 2022/9/5 10:10
 * @blog https://blog.csdn.net/biancheng4/article/details/121727982
 */

public class User {

    private Integer id;

    private Date birthday;

    private String gender;

    private String username;

    private String password;

    private String remark;

    private String station;

    private String telephone;

    @JsonIgnore
    private Set<Role> roles;

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

    public User() {
    }

    public User(Integer id, Date birthday, String gender, String username, String password, String remark, String station, String telephone) {
        this.id = id;
        this.birthday = birthday;
        this.gender = gender;
        this.username = username;
        this.password = password;
        this.remark = remark;
        this.station = station;
        this.telephone = telephone;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public String getStation() {
        return station;
    }

    public void setStation(String station) {
        this.station = station;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", birthday=" + birthday +
                ", gender='" + gender + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", remark='" + remark + '\'' +
                ", station='" + station + '\'' +
                ", telephone='" + telephone + '\'' +
                ", roles=" + roles +
                '}';
    }
}
角色类
import com.fasterxml.jackson.annotation.JsonIgnore;

import java.util.Set;

/**
 * @author 又菜又爱玩
 * @version 1.0
 * @date 2022/9/5 10:59
 * @blog https://blog.csdn.net/biancheng4/article/details/121727982
 */
public class Role {

    private Integer id;

    private String name;

    private String keyword;

    private String description;

    @JsonIgnore
    private Set<Permission> permissionSet;

    public Set<Permission> getPermissionSet() {
        return permissionSet;
    }

    public void setPermissionSet(Set<Permission> permissionSet) {
        this.permissionSet = permissionSet;
    }

    public Role() {
    }

    public Role(Integer id, String name, String keyword, String description) {
        this.id = id;
        this.name = name;
        this.keyword = keyword;
        this.description = description;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

权限类
/**
 * @author 又菜又爱玩
 * @version 1.0
 * @date 2022/9/5 13:55
 * @blog https://blog.csdn.net/biancheng4/article/details/121727982
 */
public class Permission {

    private Integer id;

    private String name;

    private String keyword;

    private String description;

    public Permission() {
    }

    public Permission(Integer id, String name, String keyword, String description) {
        this.id = id;
        this.name = name;
        this.keyword = keyword;
        this.description = description;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

注解权限

在配置文件中加上
@EnableGlobalMethodSecurity(prePostEnabled = true)
开启注解

注解的使用

 @PreAuthorize("hasAuthority('vip2')")
    @RequestMapping("/level3/{id}")
    public String toLevel3(@PathVariable("id") int id){
        return "views/level3/" + id;
    }
   <div class="column" sec:authorize="hasAuthority('SETMEAL_EDIT')">
                <div class="ui raised segment">
                    <div class="ui">
                        <div class="content">
                            <h5 class="content">Level 3</h5>
                            <hr>
                            <div><a th:href="@{/level3/1}"><i class="bullhorn icon"></i> Level-3-1</a></div>
                            <div><a th:href="@{/level3/2}"><i class="bullhorn icon"></i> Level-3-2</a></div>
                            <div><a th:href="@{/level3/3}"><i class="bullhorn icon"></i> Level-3-3</a></div>
                        </div>
                    </div>
                </div>
            </div>
    <button sec:authorize="hasRole('ADMIN')">新增</button>
     <button sec:authorize="hasAuthority('USER_DELETE')">删除</button>
            <button sec:authorize="hasAuthority('ROLE_EDIT')">修改</button>

springSecurity 文档官网:点此跳转

------------------------------ 还在学习中持续更新 ----------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值