网站用什么技术做的,如何设置网站布局,采集网站如何做,网页制作代码大全①我们需要自定义登陆接口#xff0c;也就是在controller目录新建LoginController类#xff0c;在controller方法里面去调用service接口#xff0c;在service接口实现AuthenticationManager去进行用户的认证#xff0c;注意#xff0c;我们定义的controller方法要让Spring…①我们需要自定义登陆接口也就是在controller目录新建LoginController类在controller方法里面去调用service接口在service接口实现AuthenticationManager去进行用户的认证注意我们定义的controller方法要让SpringSecurity对这个接口放行(如果不放行的话会被SpringSecurity拦截)让用户访问这个接口的时候不用登录也能访问。
②在service接口中我们通过AuthenticationManager的authenticate方法来进行用户认证,所以需要在SecurityConfig中配置把AuthenticationManager注入容器
③认证成功的话要生成一个jwt放入响应中返回。并且为了让用户下回请求时能通过jwt识别出具体的是哪个用户我们需要把用户信息存入redis可以把用户id作为key。
JwtAuthenticationTokenFilter过滤器类
package com.sangeng.filter;import com.sangeng.domain.LoginUser;
import com.sangeng.utils.JwtUtil;
import com.sangeng.utils.RedisCache;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {Autowiredprivate RedisCache redisCache;Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {//获取tokenString token request.getHeader(token);if (!StringUtils.hasText(token)) {//放行filterChain.doFilter(request, response);return;}//解析tokenString userid;try {Claims claims JwtUtil.parseJWT(token);userid claims.getSubject();} catch (Exception e) {e.printStackTrace();throw new RuntimeException(token非法);}//从redis中获取用户信息String redisKey login: userid;LoginUser loginUser redisCache.getCacheObject(redisKey);if(Objects.isNull(loginUser)){throw new RuntimeException(用户未登录);}//存入SecurityContextHolder//TODO 获取权限信息封装到Authentication中UsernamePasswordAuthenticationToken authenticationToken new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authenticationToken);//放行filterChain.doFilter(request, response);}
}在 LoginController类添加如下
package com.sangeng.controller;import com.sangeng.domain.ResponseResult;
import com.sangeng.domain.User;
import com.sangeng.service.LoginServcie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;RestController
public class LoginController {Autowiredprivate LoginServcie loginServcie;PostMapping(/user/login)public ResponseResult login(RequestBody User user){//登录return loginServcie.login(user);}
}在service目录新建 LoginService 接口
package com.huanf.service;import com.huanf.domain.ResponseResult;
import com.huanf.domain.User;
import org.springframework.stereotype.Service;/*** author 35238* date 2023/7/12 0012 11:45*/
Service
public interface LoginService {ResponseResult login(User user);
} LoginUser类
package com.sangeng.domain;import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;Data
NoArgsConstructor
public class LoginUser implements UserDetails {private User user;private ListString permissions;public LoginUser(User user, ListString permissions) {this.user user;this.permissions permissions;}JSONField(serialize false)private ListSimpleGrantedAuthority authorities;Overridepublic Collection? extends GrantedAuthority getAuthorities() {if(authorities!null){return authorities;}authorities permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());return authorities;}Overridepublic String getPassword() {return user.getPassword();}Overridepublic String getUsername() {return user.getUserName();}Overridepublic boolean isAccountNonExpired() {return true;}Overridepublic boolean isAccountNonLocked() {return true;}Overridepublic boolean isCredentialsNonExpired() {return true;}Overridepublic boolean isEnabled() {return true;}
}在LoginServiceImpl类添加如下
package com.sangeng.service.impl;import com.sangeng.domain.LoginUser;
import com.sangeng.domain.ResponseResult;
import com.sangeng.domain.User;
import com.sangeng.service.LoginServcie;
import com.sangeng.utils.JwtUtil;
import com.sangeng.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.Map;
import java.util.Objects;Service
public class LoginServiceImpl implements LoginServcie {Autowiredprivate AuthenticationManager authenticationManager;Autowiredprivate RedisCache redisCache;Overridepublic ResponseResult login(User user) {//AuthenticationManager authenticate进行用户认证UsernamePasswordAuthenticationToken authenticationToken new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());Authentication authenticate authenticationManager.authenticate(authenticationToken);//如果认证没通过给出对应的提示if(Objects.isNull(authenticate)){throw new RuntimeException(登录失败);}//如果认证通过了使用userid生成一个jwt jwt存入ResponseResult返回LoginUser loginUser (LoginUser) authenticate.getPrincipal();String userid loginUser.getUser().getId().toString();String jwt JwtUtil.createJWT(userid);MapString,String map new HashMap();map.put(token,jwt);//把完整的用户信息存入redis userid作为keyredisCache.setCacheObject(login:userid,loginUser);return new ResponseResult(200,登录成功,map);}}UserDetailsServiceImpl implements UserDetailsService
package com.sangeng.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sangeng.domain.LoginUser;
import com.sangeng.domain.User;
import com.sangeng.mapper.MenuMapper;
import com.sangeng.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
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.Arrays;
import java.util.List;
import java.util.Objects;Service
public class UserDetailsServiceImpl implements UserDetailsService {Autowiredprivate UserMapper userMapper;Autowiredprivate MenuMapper menuMapper;Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//查询用户信息LambdaQueryWrapperUser queryWrapper new LambdaQueryWrapper();queryWrapper.eq(User::getUserName,username);User user userMapper.selectOne(queryWrapper);//如果没有查询到用户就抛出异常if(Objects.isNull(user)){throw new RuntimeException(用户名或者密错误);}// ListString list new ArrayList(Arrays.asList(system:dept:list,admin));ListString list menuMapper.selectPermsByUserId(user.getId());//把数据封装成UserDetails返回return new LoginUser(user,list);}
}配置类SecurityConfig
package com.sangeng.config;import com.sangeng.filter.JwtAuthenticationTokenFilter;
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.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;Configuration
EnableGlobalMethodSecurity(prePostEnabled true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {//创建BCryptPasswordEncoder注入容器Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}Autowiredprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// 对于登录接口 允许匿名访问.antMatchers(/user/login).anonymous()
// .antMatchers(/testCors).hasAuthority(system:dept:list222)// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();//添加过滤器http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);}BeanOverridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}MenuMapper接口
package com.sangeng.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sangeng.domain.Menu;import java.util.List;public interface MenuMapper extends BaseMapperMenu {ListString selectPermsByUserId(Long userid);
}MenuMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.sangeng.mapper.MenuMapperselect idselectPermsByUserId resultTypejava.lang.StringSELECTDISTINCT m.permsFROMsys_user_role urLEFT JOIN sys_role r ON ur.role_id r.idLEFT JOIN sys_role_menu rm ON ur.role_id rm.role_idLEFT JOIN sys_menu m ON m.id rm.menu_idWHEREuser_id #{userid}AND r.status 0AND m.status 0/select
/mapper
第一步: 在你数据库的security 库新建 sys_menu权限表、sys_role角色表、sys_role_menu中间表、sys_user_role中间表并插入数据
create database if not exists security;
use security;
CREATE TABLE sys_menu (id bigint(20) NOT NULL AUTO_INCREMENT,menu_name varchar(64) NOT NULL DEFAULT NULL COMMENT 菜单名,path varchar(200) DEFAULT NULL COMMENT 路由地址,component varchar(255) DEFAULT NULL COMMENT 组件路径,visible char(1) DEFAULT 0 COMMENT 菜单状态0显示 1隐藏,status char(1) DEFAULT 0 COMMENT 菜单状态0正常 1停用,perms varchar(100) DEFAULT NULL COMMENT 权限标识,icon varchar(100) DEFAULT # COMMENT 菜单图标,create_by bigint(20) DEFAULT NULL,create_time datetime DEFAULT NULL,update_by bigint(20) DEFAULT NULL,update_time datetime DEFAULT NULL,del_flag int(11) DEFAULT 0 COMMENT 是否删除0未删除 1已删除,remark varchar(500) DEFAULT NULL COMMENT 备注,PRIMARY KEY (id)
) ENGINEInnoDB AUTO_INCREMENT2 DEFAULT CHARSETutf8mb4 COMMENT权限表;CREATE TABLE sys_role (id bigint(20) NOT NULL AUTO_INCREMENT,name varchar(128) DEFAULT NULL,role_key varchar(100) DEFAULT NULL COMMENT 角色权限字符串,status char(1) DEFAULT 0 COMMENT 角色状态0正常 1停用,del_flag int(1) DEFAULT 0 COMMENT del_flag,create_by bigint(200) DEFAULT NULL,create_time datetime DEFAULT NULL,update_by bigint(200) DEFAULT NULL,update_time datetime DEFAULT NULL,remark varchar(500) DEFAULT NULL COMMENT 备注,PRIMARY KEY (id)
) ENGINEInnoDB AUTO_INCREMENT3 DEFAULT CHARSETutf8mb4 COMMENT角色表;CREATE TABLE sys_role_menu (role_id bigint(200) NOT NULL AUTO_INCREMENT COMMENT 角色ID,menu_id bigint(200) NOT NULL DEFAULT 0 COMMENT 菜单id,PRIMARY KEY (role_id,menu_id)
) ENGINEInnoDB AUTO_INCREMENT2 DEFAULT CHARSETutf8mb4;CREATE TABLE sys_user_role (user_id bigint(200) NOT NULL AUTO_INCREMENT COMMENT 用户id,role_id bigint(200) NOT NULL DEFAULT 0 COMMENT 角色id,PRIMARY KEY (user_id,role_id)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4;insert into sys_user_role values (2,1);
insert into sys_role values
(1,经理,ceo,0,0,default,default,default,default,default),
(2,程序员,coder,0,0,default,default,default,default,default);
insert into sys_role_menu values (1,1),(1,2);
insert into sys_menu values
(1,部门管理,dept,system/dept/index,0,0,system:dept:list,#,default,default,default,default,default,default),
(2,测试,test,system/test/index,0,0,system:test:list,#,default,default,default,default,default,default)create database if not exists security;
use security;
CREATE TABLE sys_user (id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 主键,user_name VARCHAR(64) NOT NULL DEFAULT NULL COMMENT 用户名,nick_name VARCHAR(64) NOT NULL DEFAULT NULL COMMENT 昵称,password VARCHAR(64) NOT NULL DEFAULT NULL COMMENT 码,status CHAR(1) DEFAULT 0 COMMENT 账号状态0正常 1停用,email VARCHAR(64) DEFAULT NULL COMMENT 邮箱,phonenumber VARCHAR(32) DEFAULT NULL COMMENT 手机号,sex CHAR(1) DEFAULT NULL COMMENT 用户性别0男1女2未知,avatar VARCHAR(128) DEFAULT NULL COMMENT 头像,user_type CHAR(1) NOT NULL DEFAULT 1 COMMENT 用户类型0管理员1普通用户,create_by BIGINT(20) DEFAULT NULL COMMENT 创建人的用户id,create_time DATETIME DEFAULT NULL COMMENT 创建时间,update_by BIGINT(20) DEFAULT NULL COMMENT 更新人,update_time DATETIME DEFAULT NULL COMMENT 更新时间,del_flag INT(11) DEFAULT 0 COMMENT 删除标志0代表未删除1代表已删除,PRIMARY KEY (id)
) ENGINEINNODB AUTO_INCREMENT2 DEFAULT CHARSETutf8mb4 COMMENT用户表;insert into sys_user values (1,admin,管理员,{noop}123456,0,DEFAULT,DEFAULT,DEFAULT,DEFAULT,0,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT);
insert into sys_user values (2,huanf,涣沷a靑惷,$2a$10$YPnG.IYUk0mMechaxSibBuKmNeTzvuHdcxkqvoxizsll6WCQG9CHG,0,DEFAULT,DEFAULT,DEFAULT,DEFAULT,1,DEFAULT,DEFAULT,DEFAULT,DEFAULT,DEFAULT);
授权的基本流程
在SpringSecurity中会使用默认的FilterSecurityInterceptor来进行权限校验。在FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication然后获取其中的权限信息。当前用户是否拥有访问当前资源所需的权限 所以我们在项目中只需要把当前登录用户的权限信息也存入Authentication然后设置我们的资源所需要的权限即可
自定义访问路径的权限
SpringSecurity为我们提供了基于注解的权限控制方案这也是我们项目中主要采用的方式。我们可以使用注解去指定访问对应的资源所需的权限
第一步: 在SecurityConfig配置类添加如下作用是开启相关配置
EnableGlobalMethodSecurity(prePostEnabled true)
HelloController类
package com.sangeng.controller;import com.sangeng.domain.ResponseResult;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
public class HelloController {RequestMapping(/hello)PreAuthorize(ex.hasAuthority(system:dept:list222))
// PreAuthorize(hasAnyAuthority(admin,test,system:dept:list))
// PreAuthorize(hasRole(system:dept:list))
// PreAuthorize(hasAnyRole(admin,sy stem:dept:list))public ResponseResult hello(){return new ResponseResult(200,hello);}
}SGExpressionRoot.class 自定义权限类
package com.sangeng.expression;import com.sangeng.domain.LoginUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;import java.util.List;Component(ex)
public class SGExpressionRoot {public boolean hasAuthority(String authority){//获取当前用户的权限Authentication authentication SecurityContextHolder.getContext().getAuthentication();LoginUser loginUser (LoginUser) authentication.getPrincipal();ListString permissions loginUser.getPermissions();//判断用户权限集合中是否存在authorityreturn permissions.contains(authority);}
}