SpringBoot+SpringSecurity

长太息以掩涕兮,哀学习之多艰。

自学SpringBoot+SpringSecurity,遇到的问题多多,先记下吧!


pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.3.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<packaging>war</packaging> 
	<groupId>com</groupId>
	<artifactId>codeStack</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>codeStack</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			 <!-- 移除嵌入式tomcat插件
		    <exclusions>
		        <exclusion>
		            <groupId>org.springframework.boot</groupId>
		            <artifactId>spring-boot-starter-tomcat</artifactId>
		        </exclusion>
		    </exclusions> -->
		</dependency>
		<!--避坑包-->
      <dependency>
          <groupId>net.sourceforge.nekohtml</groupId>
          <artifactId>nekohtml</artifactId>
          <version>1.9.22</version>
      </dependency>
		<!-- 模版引擎 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!-- spring security依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
			<version>1.5.3.RELEASE</version>
		</dependency>

		<dependency>
		    <groupId>org.apache.tomcat</groupId>
		    <artifactId>tomcat-servlet-api</artifactId>
		    <version>9.0.20</version>
		    <scope>provided</scope>
		</dependency>
		
		<!-- 添加对 JDBC 的支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
		
		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.4.6</version>
		</dependency>
		<dependency>
	           <groupId>org.mybatis.spring.boot</groupId>
	           <artifactId>mybatis-spring-boot-starter</artifactId>
	           <version>1.3.2</version>            
	    </dependency>
	    
	     <!-- mysql driver -->
       	<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
	</dependencies>

	<build>
		<finalName>codestock</finalName>
		<plugins>
			 <plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin> 
			<plugin>
			   <groupId>org.apache.maven.plugins</groupId>
			   <artifactId>maven-war-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

application.properties

server.port=8888

spring.mvc.static-path-pattern=/static/**

#thymelea模板配置
#<!-- 关闭thymeleaf缓存 开发时使用 否则没有实时画面-->
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
#thymeleaf end

#数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/codestock?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver

#mybatis配置
mybatis.mapper-locations=classpath*:mapper/*.xml
mybatis.type-aliases-package=com.codestock.user.dao

重写WebSecurityConfigurerAdapter,使用自己的验证规则

package com.codeStack.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private MyAuthenticationProvider provider;
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// TODO Auto-generated method stub
		http
		.authorizeRequests()
		.antMatchers("/","/js/**","/css/**","/bootstrap/**","/vue/**","/images/**").permitAll()
		.anyRequest().authenticated()
		.and()
		.formLogin()
		.loginPage("/login").successForwardUrl("/code").loginProcessingUrl("/login/form").failureUrl("/login-error").permitAll()
		.and()
		.logout().logoutUrl("/logout").logoutSuccessUrl("/login").invalidateHttpSession(true).deleteCookies("JSESSIONID")
		.and()
		.csrf().disable();
		super.configure(http);
	}
	
	
	
	@Override
	@Bean
	public AuthenticationManager authenticationManagerBean() throws Exception {
		// TODO Auto-generated method stub
		return super.authenticationManagerBean();
	}
	
	//自定义用户名、密码的方式
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		// TODO Auto-generated method stub
		super.configure(auth);
		auth.authenticationProvider(provider);
	}
	
}

用户名密码验证:重写AuthenticationProvider

package com.codeStack.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;

import com.codeStack.util.MD5Util;

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

	private final static Logger logger = LoggerFactory.getLogger(MyAuthenticationProvider.class);
	
	@Autowired
	private MyUserDetailService userDetailsService;
	
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		// TODO Auto-generated method stub
		String userName = authentication.getName();//获取表单中输入的用户名
		String password = (String) authentication.getCredentials();//获取表单中输入的密码
		//判断用户是否存在、密码是否正确
		User user =  (User) userDetailsService.loadUserByUsername(userName);
		if(user==null){
			logger.error("用户名不存在!!!");
			throw new BadCredentialsException("用户名不存在!");
		}
		//一般此处密码需要做加密处理
        String inputPassword = new MD5Util().toMd5(password);
		logger.info(user.getUsername()+"登录,正确密码为:"+user.getPassword()+",登录密码为:"+inputPassword);
		
		if(!user.getPassword().equals(inputPassword)){
			logger.error("密码不正确!!!");
			throw new BadCredentialsException("密码不正确!");
		}
		//构建用户登录成功返回的token
		return new UsernamePasswordAuthenticationToken(user, password,user.getAuthorities());
	}

	@Override
	public boolean supports(Class<?> arg0) {
		// TODO Auto-generated method stub
		return true;
	}

}

调用数据库查询:重写UserDetailsService

package com.codeStack.security;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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 com.codeStack.user.dao.UserInfoDao;
import com.codeStack.user.entity.UserInfo;

@Component
public class MyUserDetailService implements UserDetailsService {

	private final static Logger logger = LoggerFactory.getLogger(MyUserDetailService.class);
	
	@Autowired
	private UserInfoDao userInfoDao;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		// TODO Auto-generated method stub
		UserInfo userInfo = userInfoDao.selectByUserName(username);
		if(userInfo!=null){
			//对应的权限添加
			List<SimpleGrantedAuthority> authorities = new ArrayList<>();
	        if(userInfo.getUserName().equals("admin")){
	        	authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
	        }else{
	        	authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
	        }
			User user = new User(username, userInfo.getPassword(), authorities);
			return user;
		}
		return null;
	}

}

由于使用thymeleaf模板引擎,在其文件夹下的html文件都需要通过controller跳转才能访问

package com.codeStack.user.controller;

import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.codeStack.security.MyAuthenticationProvider;

@Controller
public class LoginController {
	private final static Logger logger = LoggerFactory.getLogger(MyAuthenticationProvider.class);
	
	//配置自己的登录页面
	@RequestMapping("/login")
	public String login(){
		return "login";
	}
	
	//登录失败
	@RequestMapping("/login-error")
	public String loginError(){
		logger.info("登录失败....");
		return "login-error";
	}
	
	//登录成功页面
	@RequestMapping("/login/form")
	public String loginSuccess(){
		logger.info("登录成功....");
		return "code";
	}
	
	//首页为在售项目页面
	@RequestMapping("/")
	public String loginAction(){
		logger.info("进入首页....");
		return "code";
	}
	
	//在售项目页面
	@RequestMapping("/code")
	public String toCode(Map<Object,Object> map){
		map.put("msg", "模版引擎测试");
		return "code";
	}
	
	//预定项目页面
	@RequestMapping("/booking")
	public String toBooking(){
		logger.info("进入预定页面...");
		return "booking";
	}
	
	
	//个人中心页面
	@RequestMapping("/mine")
	public String toMine(){
		logger.info("进入个人中心页面...");
		return "mine";
	}
		
	
}

启动项目,访问效果如下

登录成功后如下

存在的问题:

1、登录成功后跳转到首页,但是直接刷新时会再次发送登录请求

2、首页在未登录情况下不能访问,加了.antMatchers("/","/code").permitAll()也不行

3、未登录情况下,static文件夹下的vue/vue.js会被拦截,不知如何解!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值