本人小菜鸡 见谅
pom配置
<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>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
config配置
package com.hexu.demo3.config;
import com.hexu.demo3.service.impl.UserDetailsServiceImpl;
import com.hexu.demo3.util.MD5Util;
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.PasswordEncoder;
import javax.annotation.Resource;
/**
* 安全框架
* @author 86176
*/
@EnableWebSecurity //开启
@Configuration
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Resource
UserDetailsServiceImpl userDetailsServiceImpl;
/**
* 自定义MD5加密就这样写
*
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//数据库是明文的话按下面就行了
//auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(new BCryptPasswordEncoder());
//数据库不是明文 我用的是MD5加密
auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return MD5Util.getMD5((String) charSequence);
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(MD5Util.getMD5((String) charSequence));
}
});
}
//权限认证
@Override
protected void configure(HttpSecurity http) throws Exception {
//给页面添加认证 不同级别进入不同的页面 antMatchers(“页面”) hasRole(“角色”)
http.authorizeRequests().antMatchers("/", "/lo").permitAll()
.antMatchers("/vip").hasAnyRole("VIP", "SSVIP", "SVIP")
.antMatchers("/svip").hasAnyRole("SVIP", "SSVIP")
.antMatchers("/ssvip").hasRole("SSVIP");
//没有登录返回自带的登录页面 loginPage(“自定义登陆页面”)
http.formLogin().loginPage("/lo").loginProcessingUrl("/login").successForwardUrl("/").failureUrl("/lo").permitAll();
//启动记住我功能 rememberMeParameter(“跟登陆页面的记住我复选框name值一致”)
http.rememberMe().rememberMeParameter("remember");
//退出页面 logoutSuccessUrl退出的地址
http.logout().logoutSuccessUrl("/").invalidateHttpSession(true).deleteCookies();
// 关闭 csrf 防护
http.csrf().disable();
}
}
//权限列名值要以 ROLE_开头 hasRole(ROLE_后面的权限)
工具类
md5加密
package com.hexu.demo3.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
/**
* 1.MD5(message-digest algorithm 5)信息摘要算法,
* 它的长度一般是32位的16进制数字符串(如81dc9bdb52d04dc20036dbd8313ed055)
* 2.由于系统密码明文存储容易被黑客盗取
* 3.应用:注册时,将密码进行md5加密,存到数据库中,防止可以看到数据库数据的人恶意篡改。
* 登录时,将密码进行md5加密,与存储在数据库中加密过的密码进行比对
* 4.md5不可逆,即没有对应的算法,从产生的md5值逆向得到原始数据。
* 但是可以使用暴力破解,这里的破解并非把摘要还原成原始数据,如暴力枚举法。
*
*/
public final static String getMD5(String str){
try {
MessageDigest md = MessageDigest.getInstance("SHA");//创建具有指定算法名称的摘要
md.update(str.getBytes()); //使用指定的字节数组更新摘要
byte mdBytes[] = md.digest(); //进行哈希计算并返回一个字节数组
String hash = "";
for(int i= 0;i<mdBytes.length;i++){ //循环字节数组
int temp;
if(mdBytes[i]<0) //如果有小于0的字节,则转换为正数
temp =256+mdBytes[i];
else
temp=mdBytes[i];
if(temp<16)
hash+= "0";
hash+=Integer.toString(temp,16); //将字节转换为16进制后,转换为字符串
}
return hash;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
}
service
package com.hexu.demo3.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hexu.demo3.dao.UserDao;
import com.hexu.demo3.pojo.User;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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.util.Assert;
import javax.annotation.Resource;
import java.util.*;
/**
* 数据库登录类
* @author 86176
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Resource
UserDao userDao;
@Override
public UserDetails loadUserByUsername(String s) throws AuthenticationException {
QueryWrapper<User> queryWrap=new QueryWrapper<>();
queryWrap.eq("name",s);
User user = userDao.selectOne(queryWrap);
Assert.notNull(user,"账号不存在");
//权限
List<GrantedAuthority> vip = AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRake());
// 没有用MD5加密就用这个 new BCryptPasswordEncoder().encode(user.getPass())
return new org.springframework.security.core.userdetails.User(user.getName(),user.getPass(),vip);
}
}
controller
package com.hexu.demo3.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class hello {
@RequestMapping("/")
public String home() {
return "home";
}
@RequestMapping("/lo")
public String lo() {
return "login";
}
@RequestMapping("/vip")
public String vip() {
return "vip";
}
@RequestMapping("/svip")
public String svip() {
return "svip";
}
@RequestMapping("/ssvip")
public String ssvip() {
return "ssvip";
}
}
前端页面
home.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--没有登陆显示登陆-->
<div sec:authorize="isAnonymous()">
<a href="/lo">登录</a>
</div>
<!--登陆的显示退出 并且显示当前的权限-->
<div sec:authorize="!isAnonymous()">
用户名<span sec:authentication="name"></span>
角色<span sec:authentication="authorities"></span>
<a href="/logout">退出</a>
</div>
<!--级别访问-->
<a sec:authorize="hasAnyRole('ROLE_VIP','ROLE_SSVIP','ROLE_SVIP')" href="/vip">vip通道</a>
<a sec:authorize="hasAnyRole('ROLE_SVIP','ROLE_SSVIP')" href="/svip">svip通道</a>
<a sec:authorize="hasAnyRole('ROLE_SSVIP')" href="/ssvip">大王vip通道</a>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
账号 <input type="text" name="username">
密码 <input type="password" name="password">
记住我 <input type="checkbox" name="remember">
<input type="submit" value="登录">
</form>
</body>
</html>
ssvip.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
恭喜SSVIP进入
</body>
</html>
svip.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
恭喜SVIP进入
</body>
</html>
vip.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
恭喜VIP进入
</body>
</html>