前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【第一篇】SpringSecurity的初次邂逅

【第一篇】SpringSecurity的初次邂逅

作者头像
用户4919348
发布2022-05-10 08:59:18
3760
发布2022-05-10 08:59:18
举报
文章被收录于专栏:波波烤鸭波波烤鸭

SpringSecurity的初次邂逅

image.png
image.png

一、SpringSecurity介绍

官网说明:

  Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.   Springsecurity 是一个强大的、高度可定制的身份验证和访问控制框架。它是确保基于 spring 的应用程序安全的事实标准。   Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements   Springsecurity 是一个框架,它关注于为 Java 应用程序提供身份验证和授权。像所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以很容易地扩展以满足定制需求

特征

  • 对身份验证和授权的全面且可扩展的支持
  • 保护免受会话固定,点击劫持,跨站点请求伪造等攻击
  • Servlet API集成
  • 与Spring Web MVC的可选集成

二、SpringSecurity入门案例

  我们通过一个SpringBoot项目来集成SpringSecurity的应用。

1.创建项目并添加依赖

  我们先创建一个SpringBoot项目,然后添加如下的依赖

代码语言:javascript
复制
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2.启动项目

  然后我们就可以启动项目了,项目启动会帮我们创建一个账号为 user 密码在控制台输出的登录信息。

image.png
image.png

在浏览器中提交对应的请求会直接调回到默认的登录页面。

image.png
image.png

  然后可以通过上面讲的user账号来登录,当然SpringSecurity已经帮助我们实现了认证的逻辑,如果密码输错也是登录不了的.

image.png
image.png

登录成功后就能直接请求我们需要的资源了。

image.png
image.png

报出404的原因是我们在服务端并没有index.html文件。

3.自定义登录页面

  上面的登录页面使用的是SpringSecurity中默认提供的,接下来我们需要自定义一个登录页面。前端模板通过Thymeleaf来实现,对应的添加依赖文件

代码语言:javascript
复制
        <!-- 添加thymeleaf的依赖文件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

  然后创建login.html页面文件,并放在template目录下。页面效果

image.png
image.png

  页面中的代码见附件,现在系统使用的还是默认的登录页面,我们需要替换掉,这时我们需要创建SpringSecurity的配置类.

代码语言:javascript
复制
/**
 * SpringSecurity的配置文件
 */
@Configuration
@EnableWebSecurity
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 配置需要放过的资源
                .antMatchers("/login.html","/css/**","/img/**")
                .permitAll()
                .antMatchers("/**")
                .hasAnyRole("USER")
                .anyRequest()
                .authenticated()
                .and()
                // 配置登录表单相关的信息
                .formLogin()
                // 指定自定义的登录页面
                .loginPage("/login.html")
                .permitAll();
    }
}

login.html是在template目录下的,我们没有办法直接访问,所以我们还需要定义一个controller来实现调整,对应的代码为:

代码语言:javascript
复制
@Controller
public class WebController {

    @GetMapping(value = {"/login.html"})
    public String loginPage(){
        return "login";
    }
}

  然后我们就可以重启服务来访问了。

image.png
image.png

4.自定义登录的账号

  现在登录用的账号密码是系统生成,如果我们需要使用自己的呢,我们可以在自定义的配置类中来指定

代码语言:javascript
复制
     @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 通过内存来存储账号和密码
        auth.inMemoryAuthentication()
                .withUser("zhang")
                .password("{noop}123") // {noop}非加密的方式
                .roles("USER");
    }

然后我们就可以用自定义的账号密码来登录了

image.png
image.png

5.数据库认证

  然后我们系统和关系型数据库中的用户表做认证。我们先创建对应的表结构,然后整合MyBatis来实现。

代码语言:javascript
复制
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `salt` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
)

整合MyBatis的步骤自行完成,不赘述。

  在数据库中创建了一条测试用户 admin admin

image.png
image.png

然后创建对应的SysUser对象

代码语言:javascript
复制
@Data
public class SysUser {

    private Integer id;

    private String userName;

    private String password;

    private String salt;
  
}

创建对应的UserService接口,注意这个接口必须要继承UserDetailService。

代码语言:javascript
复制
/**
 * 用户的Service
 */
public interface UserService extends UserDetailsService {

}

然后创建对应的接口实现类,在实现类中重写 loadUserByusername方法来完成根据账号查询的方法

代码语言:javascript
复制
/**
 * UserService接口的实现类
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;

    /**
     * 根据账号密码验证的方法
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser user = userMapper.queryByUserName(username);
        System.out.println("---------->"+user);
        if(user != null){
            // 账号对应的权限
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            // 说明账号存在 {noop} 非加密的使用
            UserDetails details = new User(user.getUserName(),"{noop}"+user.getPassword(),authorities);
            return details;
        }
        throw new UsernameNotFoundException("账号不存在...");

    }
}

  注意在SpringSecurity中的每个用户都需要和对应的权限绑定,所以我们在上面直接给查询的用户赋予了 USER的权限,之前在配置资源的时候其实也都要求上了。

注意:置的角色名自动加上 ‘ ROLE_ ’ 前缀。所以在数据库中将角色名设置为带 ‘ ROLE_ ’ 前缀的值便能成功访问限制的地址。

  最后修改下配置文件中的认证方式,从原来的从内存中获取认证到自定义Service认证。

image.png
image.png

  然后登录测试即可

6.加密处理

  密码的加密处理肯定是必不可少的,在SpringSecurity中推荐使用BCryptPasswordEncoder来加密,动态加盐的方式。

代码语言:javascript
复制
    public static void main(String[] args) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String password = "admin";
        // 每次都会生成一个随机的salt,同一个明文加密多次编码得到的密文其实都不一样
        System.out.println(encoder.encode(password));
        System.out.println(encoder.encode(password));
        System.out.println(encoder.encode(password));
    }

输出的信息

代码语言:javascript
复制
$2a$10$YvUoUNCvkLrokXbJkPGbH.508ho1ePHDIK5vDYWWdGiDcYwxMML6y
$2a$10$mLfDJSd0md9R28pncRVeTOtabMNOzfcIUnGHt.r/VrgAXTwm06mBO
$2a$10$owOqhXJ5kHOV7jFcERQPjuckUbmuimEfF6DqJOXskURvtqC6.NNZ6

然后在项目中我们保存生成的密文在数据库中

image.png
image.png

然后把UserService中的认证方法的逻辑修改

image.png
image.png

然后在配置文件中关联对应的加密处理

image.png
image.png

  登录测试,成功既搞定~

7.认证状态

  我们在实际项目中会因为用户的不同操作可能会出现不同的状态,比如:正常,冻结,过期等,在SpringSecurity中也是支持的。我们来看看,具体的如何来实现的。

image.png
image.png

修改认证的代码设置账号为过期的状态

image.png
image.png

登录测试效果

8.记住我

  接下来看看怎么实现RememberMe功能,首先我们需要在表单中添加 记住我 的勾选按钮

image.png
image.png
image.png
image.png

然后还得放开 记住我 的功能,默认是关闭的

image.png
image.png

然后测试:先正常登录

image.png
image.png

然后我们关闭浏览器,再登录,发现不需要登录可以访问了

image.png
image.png

  当然现在的情况是把remember-me的信息记录在内存中的,如果要实现持久化那么我们需要创建对应的表结构来记录。以下是状态持久化对应的表结构。

代码语言:javascript
复制
CREATE TABLE `persistent_logins` (
 `username` varchar(64) NOT NULL,
 `series` varchar(64) NOT NULL,
 `token` varchar(64) NOT NULL,
 `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP,
 PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

其实在JdbcTokenRepositoryImpl中帮我们定义的相关的表结构

image.png
image.png

  同时我们需要调整对应的配置文件中的配置信息

代码语言:javascript
复制
    /**
     * 向Spring容器中注入 PersistentTokenRepository 对象
     * @param dataSource
     * @return
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository(DataSource dataSource){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        return tokenRepository;
    }

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

最后在配置文件中关联

image.png
image.png

然后测试:登录成功可以看到返回的信息

image.png
image.png

同时去数据库中查看

image.png
image.png

然后关闭浏览器重新访问,发现是可以的,搞定

image.png
image.png

当你删除掉数据库中的记录后,再访问就需要登录了

image.png
image.png
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-04-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpringSecurity的初次邂逅
  • 一、SpringSecurity介绍
  • 二、SpringSecurity入门案例
    • 1.创建项目并添加依赖
      • 2.启动项目
        • 3.自定义登录页面
          • 4.自定义登录的账号
            • 5.数据库认证
              • 6.加密处理
                • 7.认证状态
                  • 8.记住我
                  相关产品与服务
                  访问管理
                  访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档