SpringSecurity(一)自定义登陆页面与基于数据库登陆

版权声明:由于本人水平有限,如有错误,不吝赐教。转载请注明出处 https://blog.csdn.net/qq_41001945/article/details/86296560

一、新建SpringBoot项目

在这里插入图片描述

二、修改配置文件

数据库结构
在这里插入图片描述

pom

<dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

        <!-- 解除thymeleaf对HTML语法的严查,不引入的话会有很多语法错误 -->
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.21</version>
        </dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

我这里的springboot版本为2.1.1.RELEASE

application.yml

spring.datasource.url=jdbc:mysql://localhost:3306/security?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123321
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

logging.level.com.springsecurity.dao=debug
spring.mvc.view.prefix=templates/
spring.mvc.view.suffix=.html

前端页面
(1)public文件夹下的login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <title>登录</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row" style="margin-top: 20px;">
        <div class="col-md-3">
            <h2>登陆</h2>
            <form action="mylogin" method="post">
                <div class="form-group">
                    <label for="userName">Username</label>
                    <input type="text" class="form-control" id="userName" name="username" placeholder="Enter username">
                </div>
                <div class="form-group">
                    <label for="password">Password:</label>
                    <input type="password" class="form-control" id="password" name="password" placeholder="Enter password">
                </div>


                <button type="submit" class="btn btn-primary">Submit</button>
            </form>
        </div>
    </div>
</div>

</body>
</html>

(2)模板引擎下的login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <title>登录</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row" style="margin-top: 20px;">
        <div class="col-md-3">
            <h2>登陆</h2>
            <form th:action="@{/mylogin}" method="post">
                <div class="form-group">
                    <label for="userName">Username</label>
                    <input type="text" class="form-control" id="userName" name="username" placeholder="Enter username">
                </div>
                <div class="form-group">
                    <label for="password">Password:</label>
                    <input type="password" class="form-control" id="password" name="password" placeholder="Enter password">
                </div>

                <div class="form-group" th:if="${param.error}">
                    <p th:if="${session.SPRING_SECURITY_LAST_EXCEPTION}">
                    <p th:text="${session.SPRING_SECURITY_LAST_EXCEPTION.message}"></p>
                    </p>
                </div>

                <button type="submit" class="btn btn-primary">Submit</button>
            </form>
        </div>
    </div>
</div>

</body>
</html>

SpringSecurityConfig

package com.springsecurity.config;

import com.springsecurity.service.MyUserService;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.Md4PasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserService myUserService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/","/login.html","/testlogin","/mylogin") // 不需要登录就可以访问
                .permitAll()
                .antMatchers("/user/**").hasAnyRole("USER") // 需要具有ROLE_USER角色才能访问
                .antMatchers("/admin/**").hasAnyRole("ADMIN") // 需要具有ROLE_ADMIN角色才能访问
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/testlogin") // 设置登录页面
                .loginProcessingUrl("/mylogin")
                .defaultSuccessUrl("/index") // 设置默认登录成功后跳转的页面
        ;
    }

    // 密码加密方式
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    // 重写方法,自定义用户
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserService);
    }
}

必要说明:
loginPage("/testlogin") 相当于一个普通请求。这里则需要发送到登陆页面
loginProcessingUrl("/mylogin") 登陆页面表单提交的action.必须为post请求
defaultSuccessUrl("/index") 登陆成功后,发送这个请求

Controller接受处理请求

package com.springsecurity.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;

@Controller
public class UserController {

    @GetMapping("/testlogin")
    public String authenticationLogin() throws IOException {
        return "login";
    }

    @GetMapping("/")
    public String welcome(){
        return "redirect:/login.html";
    }

    @GetMapping("/index")
    @ResponseBody
    public String index() throws IOException {
        return "index html";
    }
}

UserDetailService

package com.springsecurity.service;

import com.springsecurity.bean.User;
import com.springsecurity.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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 java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Service
public class MyUserService implements UserDetailsService {
    @Autowired
    private UserDao userDao;

    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //从数据库根据用户名获取用户信息
        System.out.println(s);
        User userByName = userDao.getUserByName(s);
        //创建一个新的UserDetails对象,最后验证登陆的需要
        UserDetails userDetails=null;
        if(userByName!=null){
            System.out.println(userByName.getPassword());
            //创建一个集合来存放权限
            Collection<GrantedAuthority> authorities = getAuthorities(userByName);
            //实例化UserDetails对象
            userDetails=new org.springframework.security.core.userdetails.User(s,userByName.getPassword(),true,true,true,true, authorities);
        }
        return userDetails;
    }

    private Collection<GrantedAuthority> getAuthorities(User user){
        List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
        //注意:这里每个权限前面都要加ROLE_。否在最后验证不会通过
        authList.add(new SimpleGrantedAuthority("ROLE_"+user.getRole()));
        return authList;
    }
}

Dao层

扫描二维码关注公众号,回复: 4882450 查看本文章
package com.springsecurity.dao;

import com.springsecurity.bean.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserDao {

    @Select("SELECT * FROM user where username=#{s}")
    public User getUserByName(String s);
}

实体类JavaBean

package com.springsecurity.bean;

import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@ToString
public class User{

    private Integer id;
    private String username;
    private String password;
    private String role;

}

启动boot项目,验证登陆

在这里插入图片描述
在这里插入图片描述

在经过测试的时候,我发现直接访问模板引擎下面的页面会报404而在resources下创建public文件夹,里面放html文件就不会出404. 因为模板引擎相当于我们传统的ssm项目里面的WEB-INF文件夹。是受保护的。不能重定向以及直接访问。 转发没问题。所以,两个不同页面下的请求发送会有一点点差别。具体看上面代码。

form-login是spring security命名空间配置登录相关信息的标签,它包含如下属性: 
1. login-page 自定义登录页url,默认为/login 
2. login-processing-url 登录请求拦截的url,也就是form表单提交时指定的action 
3. default-target-url 默认登录成功后跳转的url 
4. always-use-default-target 是否总是使用默认的登录成功后跳转url 
5. authentication-failure-url 登录失败后跳转的url 
6. username-parameter 用户名的请求字段 默认为userName 
7. password-parameter 密码的请求字段 默认为password 
8. authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用 
9. authentication-success-forward-url 用于authentication-failure-handler-ref 
10. authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求 
11. authentication-failure-forward-url 用于authentication-failure-handler-ref 
12. authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用

猜你喜欢

转载自blog.csdn.net/qq_41001945/article/details/86296560
今日推荐