首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringSecurity入坑(二)

SpringSecurity入坑(二)

原创
作者头像
是小张啊喂
修改2021-04-14 14:13:32
3100
修改2021-04-14 14:13:32
举报
文章被收录于专栏:软件软件

上一次实现了基于内存验证 缺少了实际的可用性现在修改一下 SpringSecurity的配置来实现基本的数据库验证

pom.xml依赖请参考SpringSecurity入坑(一)的具体依赖这里不做修改

基于数据库做验证,主要的是构建权限验证 废话不多 XX 直接上CODE

User用户表,基于SpringDataJpa构建User用户表

package com.shaojie.authority.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;

import javax.persistence.*;

/**
 * @author ShaoJie
 * @Date 2019年11月25 17:49
 * @Description:
 */
@Data
@Entity
@AllArgsConstructor
@Accessors(chain = true)
@Table(name = "user")
public class User {

    /**
     * 用户的自增 id
     */
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    /**
     * 用户的账号
     */
    @Column(name = "name")
    private String name;

    /**
     * 用户的密码
     */
    @Column(name = "password")
    private String password;

    /**
     * 账号是否启用
     */
    @Column(name = "enable")
    private Boolean enable;

    public User() {

    }

}

Authority权限表 保存用户的权限

package com.shaojie.authority.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;

import javax.persistence.*;

/**
 * @author: ShaoJie
 * @data: 2020年01月06日 20:22
 * @Description: 用户的权限
 */
@Data
@Entity
@AllArgsConstructor
@Accessors(chain = true)
@Table(name = "authority")
public class Authority {

    /**
     * 用户的自增 id
     */
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    /**
     * 用户的账号
     */
    @Column(name = "member_id")
    private Integer memberId;

    /**
     * 用户的权限
     */
    @Column(name = "authority")
    private String authority;

    public Authority() {

    }
}

User数据访问层

package com.shaojie.authority.dao;

import com.shaojie.authority.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @author ShaoJie
 * @Date 2019年11月25 18:46
 * @Description:
 */
public interface UserRepository extends JpaRepository<User, Integer> {
    /**
     * 根据用户的账号查询用户
     *
     * @param name 用户的账号
     * @return 用户信息
     */
    User findUserByName(String name);
}

User的业务逻辑层

package com.shaojie.authority.service;

import com.shaojie.authority.model.User;

/**
 * @author ShaoJie
 * @Date 2019年11月25 18:49
 * @Description:
 */
public interface UserService {

    /**
     * 根据用户的账号查询用户
     *
     * @param name 用户的账号
     * @return 用户信息
     */
    User findUserByName(String name);

}

Authority的业务逻辑层

package com.shaojie.authority.dao;

import com.shaojie.authority.model.Authority;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @author: ShaoJie
 * @data: 2020年01月06日 21:10
 * @Description: 权限 数据访问层
 */
public interface AuthorityRepository extends JpaRepository<Authority, Integer> {
}

Authority的业务逻辑层

package com.shaojie.authority.service;

import com.shaojie.authority.model.Authority;

import java.util.List;

/**
 * @author: ShaoJie
 * @data: 2020年01月06日 21:14
 * @Description: 权限的业务逻辑层
 */
public interface AuthorityService {

    /**
     * 获取用户的权限
     *
     * @param memberId 用户的 id
     * @return 权限的集合
     */
    List<Authority> getUserAuthority(Integer memberId);
}

Authority的业务逻辑 impl

package com.shaojie.authority.service.impl;

import com.shaojie.authority.dao.AuthorityRepository;
import com.shaojie.authority.model.Authority;
import com.shaojie.authority.service.AuthorityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author: ShaoJie
 * @data: 2020年01月06日 21:14
 * @Description: 权限的业务逻辑层
 */
@Service
@Transactional
public class AuthorityServiceImpl implements AuthorityService {

    /**
     * 权限数据访问层
     */
    @Autowired
    private AuthorityRepository authorityRepository;

    /**
     * 获取用户的权限
     *
     * @param memberId 用户的 id
     * @return 权限的集合
     */
    @Override
    public List<Authority> getUserAuthority(Integer memberId) {
        Example<Authority> example = Example.of(new Authority()
                .setMemberId(memberId));
        return authorityRepository.findAll(example);
    }
}

User的业务逻辑 impl

package com.shaojie.authority.security;

import com.shaojie.authority.model.Authority;
import com.shaojie.authority.model.User;
import com.shaojie.authority.service.UserService;
import com.shaojie.authority.service.impl.AuthorityServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.ArrayList;
import java.util.List;

/**
 * @author ShaoJie
 * @Date 2019年11月26 19:48
 * @Description:
 */
@Service
@Transactional
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {

    /**
     * 用户 业务逻辑层
     */
    @Autowired
    private UserService userService;

    /**
     * 权限 业务逻辑层
     */
    @Autowired
    private AuthorityServiceImpl authorityService;

    /**
     * 密码加密
     */
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    /**
     * 加载登录 通过用户名查找用户
     *
     * @param userName 登录的用户名称
     * @return 用户信息
     * @throws UsernameNotFoundException 未找到用户登录名称信息
     */
    @Transactional(readOnly = true)
    @Override
    public UserDetails loadUserByUsername(@RequestParam String userName) throws UsernameNotFoundException {
        log.info("{ 当前登录的用户账号:  {} }", userName);
        User user = userService.findUserByName(userName);
        List<GrantedAuthority> authorityList =  new ArrayList<>();
        if (user != null) {
            // 权限集合 当前用户所具有的权限
            authorityList = getUserAuthority(user.getId());
        }
        return new org.springframework.security.core.userdetails.User(user.getName(), bCryptPasswordEncoder.encode(user.getPassword()), authorityList);
    }

    /**
     * 连接数据库 实现 读取权限集合
     *
     * @return 授予的权限
     */
    public List<GrantedAuthority> getUserAuthority(Integer memberId) {
        // 创建权限集合
        List<GrantedAuthority> authorityList = new ArrayList<>();
        // 读取用户的权限集合
        List<Authority> userAuthority = authorityService.getUserAuthority(memberId);
        for (Authority a : userAuthority) {
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(a.getAuthority());
            authorityList.add(grantedAuthority);
        }
        return authorityList;
    }

}

这里我直接都写在一起了 ,并没有细划分,其实这个分层不应该是这样,这里只是做基础的展示,所以可能代码上有些糙,有兴趣的自己做调整,下面就是关键的一步了,那就是构建权限验证

构建权限验证

package com.shaojie.authority.security;

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.method.configuration.EnableGlobalMethodSecurity;
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;

/**
 * @author ShaoJie
 * @Date 2019/10/25
 */
@Configuration
// 启动 SpringSecurity 的过滤器链
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 密码加密
     *
     * @return
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public UserDetailsServiceImpl userDetailsService() {
        return new UserDetailsServiceImpl();
    }

    /**
     * 用户详细信息 业务逻辑层
     */
    @Autowired
    public UserDetailsServiceImpl userDetailsService;

    /**
     * 授权
     *
     * @param auth
     * @throws Exception
     */
    // 代替配置文件 <security:authentication-manager></security:authentication-manager>
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 基于 数据库验证
        auth.userDetailsService(userDetailsService());
    }

    /**
     * 验证
     *
     * @param http
     * @throws Exception
     */
    // 代替配置文件 <security:http></security:http>
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                // antMatchers 设置拦截的请求  hasAnyAuthority 对应的权限名称
                // .hasAnyAuthority("PRODUCT_ADD") 用户所具有的权限
                .antMatchers("/product/add").hasAnyAuthority("PRODUCT_ADD")
                .antMatchers("/product/update").hasAnyAuthority("PRODUCT_UPDATE")
                .antMatchers("/product/list").hasAnyAuthority("PRODUCT_LIST")
                .antMatchers("/product/delete").hasAnyAuthority("PRODUCT_DELETE")
                // permitAll 所有的权限都能访问
                .antMatchers("/login").permitAll()
//                .antMatchers("/**")
                // fullyAuthenticated 不允许匿名用户查看
//                .fullyAuthenticated()
                // 设置所有的请求都必须经过验证才能访问
                .anyRequest().authenticated()
                .and()
                // httpbasic 登录
                // .httpBasic();
                // 表单登录
                .formLogin()
                //  登录请求的页面
                .loginPage("/login")
                // 处理登录请求的 地址
                .loginProcessingUrl("/index")
                // 修改 spring 提供的 默认登陆参数
                .usernameParameter("userName")
                .passwordParameter("password")
                .and()
                // 开启记住我功能
                .rememberMe()
                .and()
                // 开启登出
                .logout()
                .and()
                // 禁用跨域的保护
                .csrf().disable();

    }
}

这里需要注意的就是 权限这里 ,现在只 先做到写死权限,系统所具有的哪些权限,这里需要在数据库中配置,后续继续整理,还需要主要的是,需要配置处理登录请求的 地址,基于上一章SpringSecurity入坑(一)页面需要做一下修改:

login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h2>登录页面</h2>
    <form th:action="@{/index}" method="post">
        账号:<input type="text" name="userName" value="1591313226@163.com"><br>
        密码:<input type="password" name="password" value="123456"><br>
        <button type="submit">登录</button>
    </form>
</body>
</html>

需要注意的是,这里的提交的 method 一定要是 post

到这基本的访问数据库,操作权限验证,就到这里,SpringSecurity提供了很多,我们慢慢学习,尽量把这个吸收好。这条路还有很长,需要慢慢的接触,不能太过着急

喜欢编程的,请关注我的博客https://www.lzmvlog.top/

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • User用户表,基于SpringDataJpa构建User用户表
  • Authority权限表 保存用户的权限
  • User数据访问层
  • User的业务逻辑层
  • Authority的业务逻辑层
  • Authority的业务逻辑层
  • Authority的业务逻辑 impl层
  • User的业务逻辑 impl层
  • 构建权限验证
    • login.html
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档