文章目录
pom文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
//前后端分离可以不用引下面的thymeleaf
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
在前后端不分离使用thymeleaf,会有一个默认的登录,第一次弄的时候找了半天没找出来这个页面在哪里cao
Config配置类
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 用来定义哪些请求需要忽略安全控制,哪些请求必须接受安全控制;还可以在合适的时候清除SecurityContext以避免内存泄漏,
* 同时也可以用来定义请求防火墙和请求拒绝处理器,另外我们开启Spring Security Debug模式也是这里配置的
*/
@Override
public void configure(WebSecurity web) throws Exception {
//super.configure(web);
web.ignoring()
.antMatchers("/js/**",
"/assets/**","/data/**","/files/**"
,"/fonts/**","/lib/**","/plugins/**","/resources/**"
,"/vendors/**",
"/css/**", "/images/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http);
http.formLogin()
//登录页面在static中直接xx.html,在thmplates中需要controller请求返回
.loginPage("/user/tologin").permitAll()
// .loginPage("/myLogin.html").permitAll()
//指登录成功后,是否始终跳转到登录成功url。它默认为false
.defaultSuccessUrl("/user/dologin", true)
// //post登录接口,登录验证由系统实现
.loginProcessingUrl("/user/login")
//用户密码错误跳转接口
.failureUrl("/error.html")
//要认证的用户参数名,默认username,自定义登录逻辑,对应html中的name
.usernameParameter("username")
//要认证的密码参数名,默认password
.passwordParameter("password")
//配置注销
.and()
.logout()
//自定义注销接口
.logoutUrl("/logout")
//注销成功后跳转到的接口
.logoutSuccessUrl("/user/tologin").permitAll()
//删除自定义的cookie
.deleteCookies("token");
//3.进一步配置自定义的登录页面
//拦截请求,创建FilterSecurityInterceptor
http.authorizeRequests()
.antMatchers("/user/tologin/**","/user/usermessage","/user/toeditmember","/user/password").permitAll()
.antMatchers("/user/dologin","/user/paySuccess").permitAll()
.antMatchers("/user/toindex","/notice/transaction","/notice/toPay","/notice/toPay1","/notice/toLogistics","/notice/secondReg").permitAll()
.antMatchers("/user/e","/user/exportAccount").hasAuthority("admin")
.antMatchers("/user/doregister","/user/toregister").permitAll()
.antMatchers("/notice_cy/unnoticeable","notice_cy/Notify_editor","user/companymessage","/user/docompanymessage").hasAuthority("admin")
.antMatchers("/notice/qgcheck","/notice/spqg","notice_cy/Notify_editor","user/companymessage","/user/buyercenter","/user/dozhaipai2").hasAuthority("buyer")
.antMatchers("/notice/gpcheck","/notice/gp","notice_cy/Notify_editor","user/companymessage","/user/sellercenter","/user/dozhaipai1").hasAuthority("seller")
.antMatchers("/order/alipay").permitAll()
.antMatchers("/notice/admin","/user/dousermessage/**",
"/user/password/**"
).hasAuthority("admin")
//访问权限控制
// .antMatchers("/error.html").hasAuthority("vip1")
// .antMatchers("/main1.html").hasAnyAuthority("adMin","admiN")
// .antMatchers("/main1.html").hasRole("abc")
//访问静态资源,约定请求格式
// .antMatchers(HttpMethod.POST,"/images/**").permitAll()
//除以上的请求不拦截外其他任何请求都必须被认证
.anyRequest().authenticated()
//用and来表示配置过滤器结束,以便进行下一个过滤器的创建和配置
.and()
//设置表单登录,创建UsernamePasswordAuthenticationFilter
//注意:需禁用crsf防护功能,否则登录不成功
.csrf().disable()
.headers().frameOptions().disable();
}
@Bean
public PasswordEncoder getPw(){
return new BCryptPasswordEncoder();
}
}
自定义登录逻辑
设置了自定义登录请求后将走自定义登录逻辑,而不走Controller了
@Service
public class UserServicedetail implements UserDetailsService {
@Autowired
private PasswordEncoder pw;
@Autowired
private UserService userService;
public static Account account=new Account();
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
account =userService.getuserbyname(username);
if (account==null) {
throw new UsernameNotFoundException("用户名不存在");
}
//1.查询数据库判断用户名是否存在,如果不存在抛出
String password = pw.encode(account.getPassword());
System.out.println(account.getRole());
switch (account.getRole())
{
//2.把查询出来的密码(注册时已经加密过)进行解析,或直接把密码放入构造方法
//赋权
case 1:{
System.out.println(username+account.getPassword()+"赋予了admin权限");
return new User(username,password,
AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal,ROLE_abc"));
}
case 2:{
System.out.println(username+account.getPassword()+"赋予了buyer权限");
return new User(username,password,
AuthorityUtils.commaSeparatedStringToAuthorityList("buyer"));
}
case 3:{
System.out.println(username+account.getPassword()+"赋予了seller权限");
return new User(username,password,
AuthorityUtils.commaSeparatedStringToAuthorityList("seller"));
}
default:
return new User(username,password,
AuthorityUtils.commaSeparatedStringToAuthorityList(""));
}
}
}
使用thymeleaf引入权限控制
html的命名空间加入
<html xmlns:th="http://www.thymeleaf.org"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
后台管理系统大多都是一个模板,但要针对不同的用户,如果制作多套页面按权来返回的话,感觉不太好,因此直接在一个页面上引入多个功能
这里是侧滑栏,求购审核和商品挂牌是在同一个页面,但不同权限的人只能看到属于它权限的东西
需要这两HttpServletRequest request, HttpServletResponse response
jwt创建和解析token
public class jwt {
public String testCreatTokenByClaims(String username,String password) {
//当前系统时间的长整型
long now = System.currentTimeMillis();
//过期时间,这里是60分钟后的时间长整型
long exp = now + 60 * 1000*60*24;
//创建一个JwtBuilder对象
JwtBuilder jwtBuilder = Jwts.builder()
//声明的标识{"jti":"888"}
.setId("888")
//主体,用户{"sub":"Rose"}
.setSubject("Rose")
//创建日期{"ita":"yjxxtxx"}
.setIssuedAt(new Date())
//签名手段,参数1:算法,参数2:盐
.signWith(SignatureAlgorithm.HS256, "yjxxt")
//设置过期时间
.setExpiration(new Date(exp))
//直接传入map
// .addClaims(map)
.claim("username",username)
.claim("password",password)
.claim("roles","admin");
//获取jwt的token
String token = jwtBuilder.compact();
System.out.println(token);
return token;
}
public Map<String, String> testParseTokenByClaims(String token) {
//token
//解析token获取负载中的声明对象
Claims claims = Jwts.parser()
.setSigningKey("yjxxt")
.parseClaimsJws(token)
.getBody();
Map<String,String > userMap=new HashMap<>();
//打印声明的属性
System.out.println("id:" + claims.getId());
System.out.println("subject:" + claims.getSubject());
System.out.println("issuedAt:" + claims.getIssuedAt());
DateFormat sf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("签发时间:"+sf.format(claims.getIssuedAt()));
System.out.println("过期时间:"+sf.format(claims.getExpiration()));
System.out.println("当前时间:"+sf.format(new Date()));
System.out.println("roles:"+claims.get("roles"));
userMap.put("username", claims.get("username").toString());
userMap.put("password", claims.get("password").toString());
userMap.put("roles", claims.get("roles").toString());
return userMap;
}
把token存到浏览器
jwt jwt=new jwt();
String token=jwt.testCreatTokenByClaims(username,account.getPassword());
Cookie cookie=new Cookie("token","cookievalue");
cookie.setMaxAge(60 * 1000*60*24);
cookie.setPath("/");
cookie.setValue(token);
response.addCookie(cookie);
查看本地的cookies
Cookie rcookie = null;
Cookie[] cookies=request.getCookies();
for (Cookie x:cookies) {
if(x.getName().equals("token"))
{
rcookie=x;
System.out.println("存在"+rcookie.getName()+" "+rcookie.getValue());
break;
}
}