Spring Security实现JDBC用户登录认证

在搭建博客后端服务框架时,我采用邮件注册+Spring Security登录认证方式,结合mysql数据库,给大家展示下具体是怎么整合的。

 

本篇是基于上一篇:spring boot实现邮箱验证码注册

 

1.引入Spring Security相关依赖

<!--spring security-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
            <version>3.0.2.RELEASE</version>
        </dependency>

 

2.添加相关页面

2.1 login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <title>Spring Security Example </title>
</head>
<body>
<div th:if="${param.error}" style="color: red;">
    用户名或密码错误!
</div>
<div th:if="${param.logout}" style="color: darkgreen;">
    注销成功!
</div>
<form th:action="@{/login}" method="post">
    <div><label> 用户名 : <input type="text" name="username"/> </label></div>
    <div><label> 密码: <input type="password" name="password"/> </label></div>
    <div><input type="submit" value="submit"/> <input type="reset" value="reset"/></div>
</form>
<p>Click <a th:href="@{/welcome}">here</a> go to home page.</p>
</body>
</html>

 

3.创建User表及实体类

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  `active_code` varchar(100) DEFAULT NULL,
  `active_status` int(11) DEFAULT '0',
  `roles` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
package com.laoxu.easyblog.entity;

import lombok.Data;

import java.io.Serializable;

/**
 * @description: 用户
 * @author: luohanye
 * @create: 2019-04-17
 **/

@Data
public class User implements Serializable {
    private Integer id;
    private String username;
    private String password;
    private String email;
    // 激活状态 0 未激活 1 已激活
    private Integer activeStatus;
    // 激活码
    private String activeCode;
    // 角色
    private String roles;
}

 

4.创建自定义UserDetailService实现类

package com.laoxu.easyblog.service;

import com.laoxu.easyblog.dao.UserDao;
import com.laoxu.easyblog.entity.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
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.Service;

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

/**
 *  自定义UserService
 */
@Service
public class MyUserService<T extends User> implements UserDetailsService {
    @Autowired
    private UserDao userDao;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        try {
            User user = userDao.selectByUsername(username);
            if (user == null) {
                throw new UsernameNotFoundException("用户名不存在");
            }
            //用户权限
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            if (StringUtils.isNotBlank(user.getRoles())) {
                String[] roles = user.getRoles().split(",");
                for (String role : roles) {
                    if (StringUtils.isNotBlank(role)) {
                        authorities.add(new SimpleGrantedAuthority(role.trim()));
                    }
                }
            }
            return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

5.创建MD5工具类

package com.laoxu.easyblog.common;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 *  md5工具类
 */
public class MD5Util {
    public static final int time = 5;

    public static final String SALT = "springsecurity";

    /**
     * 密码加密方法
     *
     * @param password
     * @return
     */
    public static String encode(String password) {
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("MD5 algorithm not available.  Fatal (should be in the JDK).");
        }
        try {
            for (int i = 0; i < time; i++) {
                byte[] bytes = digest.digest((password + SALT).getBytes("UTF-8"));
                password = String.format("%032x", new BigInteger(1, bytes));
            }
            return password;
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("UTF-8 encoding not available.  Fatal (should be in the JDK).");
        }
    }

    public static void main(String[] args) {
        System.out.println(MD5Util.encode("123456"));
    }
}

 

6.创建自定义密码验证类

package com.laoxu.easyblog.common;

import org.springframework.security.crypto.password.PasswordEncoder;

public class MyPasswordEncoder implements PasswordEncoder {

    @Override
    public String encode(CharSequence rawPassword) {
        return MD5Util.encode((String) rawPassword);
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        //user Details Service验证
        return encodedPassword.equals(MD5Util.encode((String) rawPassword));
    }
}

 

7.添加Spring Security配置

package com.laoxu.easyblog.config;


import com.laoxu.easyblog.common.MyPasswordEncoder;
import com.laoxu.easyblog.entity.User;
import com.laoxu.easyblog.service.MyUserService;
import org.springframework.beans.factory.annotation.Autowired;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * Spring Security配置
 *
 * @author xusucheng
 * @create 2018-10-26
 **/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/*    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource);
    }*/

    @Resource
    private MyUserService<User> userService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(new MyPasswordEncoder());
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers("/css/**", "/js/**", "/fonts/**", "/images/**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/welcome").hasRole("ADMIN")
                .and().formLogin().loginPage("/login").permitAll().defaultSuccessUrl("/welcome")
                .and().logout().permitAll()
                ;

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //忽略
        web.ignoring().antMatchers("/wd/**");
    }
}

 

8.配置视图转发器

 

package com.laoxu.easyblog.config;

import com.laoxu.easyblog.interceptor.LoginHandlerInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * @author xusucheng
 * @create 2018-10-23
 **/

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Value("${spring.mvc.view.prefix}")
    private String prefix="";

    @Value("${spring.mvc.view.suffix}")
    private String suffix="";

    @Value("${spring.mvc.view.view-name}")
    private String viewName="";



    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/static/assets/");
        registry.addResourceHandler("/wd/**").addResourceLocations("classpath:/wd/");
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
        registry.addViewController("/welcome").setViewName("welcome");
    }

    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix(prefix);
        resolver.setSuffix(suffix);
        resolver.setViewClass(JstlView.class);
        resolver.setViewNames(viewName);
        return resolver;
    }

   /* @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/register","/assets/**","/wd/**","/account/changePwd","/account/add");
    }*/
}

 

9.测试

9.1 注册账号

访问:localhost:8080 先注册一个账号,例如:lisi 123

9.2 激活账号

9.3 登录失败,没有ROLE_ADMIN权限

9.4 登录成功,添加用户权限为ROLE_ADMIN

 

 

 

 

 

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,关于你的问题,我可以回答如下: 首先,你需要在Spring Security配置文件中配置数据库连接信息,具体步骤如下: 1. 导入Spring SecurityJDBC相关的依赖。 ```xml <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>5.3.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>5.3.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.8.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency> ``` 2. 在Spring配置文件中配置数据库连接信息。 ```xml <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <!-- 配置Spring Security --> <security:http auto-config="true"> <security:intercept-url pattern="/admin/**" access="ROLE_ADMIN"/> <security:form-login login-page="/login" default-target-url="/welcome" authentication-failure-url="/login?error"/> <security:logout logout-success-url="/login?logout"/> </security:http> <security:authentication-manager> <security:authentication-provider> <security:jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password,enabled from users where username=?" authorities-by-username-query="select username,authority from authorities where username=?"/> </security:authentication-provider> </security:authentication-manager> ``` 其中,`users-by-username-query`和`authorities-by-username-query`分别用于查询用户信息和用户权限信息。这里的查询语句需要根据实际情况进行修改。 接下来,你需要实现用户固定授权。可以通过在数据库中添加一个`authorities`表来实现。表结构如下: ```sql CREATE TABLE authorities ( username VARCHAR(50) NOT NULL, authority VARCHAR(50) NOT NULL, PRIMARY KEY (username,authority), CONSTRAINT fk_authorities_users FOREIGN KEY(username) REFERENCES users(username) ); ``` 然后,在`authorities`表中添加用户的角色信息。例如,如果用户`admin`具有`ROLE_ADMIN`角色,则可以添加如下记录: ```sql INSERT INTO authorities(username,authority) VALUES('admin','ROLE_ADMIN'); ``` 这样,当用户`admin`登录时,就会被授予`ROLE_ADMIN`角色。 以上就是实现Spring Security连接数据库并实现用户固定授权的基本步骤。希望我的回答能够帮助到你!
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值