Spring Security
登录先执行认证
1
//登录认证
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {}
得到用户名密码
执行会调用 1.1
根据用户名查询用户信息和所具有的权限,然后通过security对象返回
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
/***
* 根据账号获取用户信息,
* @param username:
* @return: org.springframework.security.core.userdetails.UserDetails
*/}
登录过程中会查数据库 调用
package com.yzh.aclservice.service.impl;
import com.yzh.aclservice.entity.User;
import com.yzh.aclservice.service.PermissionService;
import com.yzh.aclservice.service.UserService;
import com.yzh.serurity.entity.SecurityUser;
import org.springframework.beans.BeanUtils;
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.List;
/**
* <p>
* 自定义userDetailsService - 认证用户详情
* </p>
*
*/
//实现security的实现类
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private PermissionService permissionService;
/***
* 根据账号获取用户信息
* @param username:
* @return: org.springframework.security.core.userdetails.UserDetails
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 从数据库中取出用户信息
User user = userService.selectByUsername(username);
// 判断用户是否存在
if (null == user){
//throw new UsernameNotFoundException("用户名不存在!");
}
// 返回UserDetails实现类
com.yzh.serurity.entity.User curUser = new com.yzh.serurity.entity.User();
BeanUtils.copyProperties(user,curUser);
//查询权限
List<String> authorities = permissionService.selectPermissionValueByUserId(user.getId());
SecurityUser securityUser = new SecurityUser(curUser);
securityUser.setPermissionValueList(authorities);
return securityUser;
}
}
2.如果认证正确
会执行认证过滤器的
successfulAuthentication方法
//登录认证
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {}
得到用户信息,根据用户信息得到token值,并且把用户名,和权限信息生成一个token值,
并且把查询出来的权限,和用户信息放到redis中,用户名作为key
然后把token 返回
/**
* 登录成功
* @param req
* @param res
* @param chain
* @param auth
* @throws IOException
* @throws ServletException
*/
@Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
Authentication auth) throws IOException, ServletException {
SecurityUser user = (SecurityUser) auth.getPrincipal();
String token = tokenManager.createToken(user.getCurrentUserInfo().getUsername());
//用户信息放入缓存
redisTemplate.opsForValue().set(user.getCurrentUserInfo().getUsername(), user.getPermissionValueList());
ResponseUtil.out(res, R.ok().data("token", token));
}
如果认证失败调用
认证中的失败方法
/**
* 登录失败
* @param request
* @param response
* @param e
* @throws IOException
* @throws ServletException
*/
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException e) throws IOException, ServletException {
ResponseUtil.out(response, R.error());
}
package com.yzh.serurity.filter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yzh.serurity.entity.SecurityUser;
import com.yzh.serurity.entity.User;
import com.yzh.serurity.security.TokenManager;
import com.yzh.utils.ResponseUtil;
import com.yzh.utils.ordervo.R;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
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.ArrayList;
/**
* <p>
* 登录过滤器,继承UsernamePasswordAuthenticationFilter,对用户名密码进行登录校验
* </p>
*
* @author qy
* @since 2019-11-08
*/
//登录认证
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
private TokenManager tokenManager;
private RedisTemplate redisTemplate;
public TokenLoginFilter(AuthenticationManager authenticationManager, TokenManager tokenManager, RedisTemplate redisTemplate) {
this.authenticationManager = authenticationManager;
this.tokenManager = tokenManager;
this.redisTemplate = redisTemplate;
this.setPostOnly(false);
//当前登录请求地址
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/acl/login","POST"));
}
//得到登录时候的账号密码
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException {
try {
User user = new ObjectMapper().readValue(req.getInputStream(), User.class);
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 登录成功
* @param req
* @param res
* @param chain
* @param auth
* @throws IOException
* @throws ServletException
*/
@Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
Authentication auth) throws IOException, ServletException {
SecurityUser user = (SecurityUser) auth.getPrincipal();
String token = tokenManager.createToken(user.getCurrentUserInfo().getUsername());
//用户信息放入缓存
redisTemplate.opsForValue().set(user.getCurrentUserInfo().getUsername(), user.getPermissionValueList());
ResponseUtil.out(res, R.ok().data("token", token));
}
/**
* 登录失败
* @param request
* @param response
* @param e
* @throws IOException
* @throws ServletException
*/
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException e) throws IOException, ServletException {
ResponseUtil.out(response, R.error());
}
}
认证后授权过滤器
授权过滤器
1
从heard 获得token信息,根据用户获取redis中的权限信息,然后给用户授权
/取信息判断有没有权限,进行授权处理
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
// token置于header里
String token = request.getHeader("token");
if (token != null && !"".equals(token.trim())) {
// 解析Tocken
String userName = tokenManager.getUserFromToken(token);
//根据用户从redis中取出
List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
//封装权限
Collection<GrantedAuthority> authorities = new ArrayList<>();
for(String permissionValue : permissionValueList) {
if(StringUtils.isEmpty(permissionValue)) continue;
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
authorities.add(authority);
}
if (!StringUtils.isEmpty(userName)) {
//封装
return new UsernamePasswordAuthenticationToken(userName, token, authorities);
}
return null;
}
return null;
}
package com.yzh.serurity.filter;
import com.yzh.serurity.security.TokenManager;
import com.yzh.utils.ResponseUtil;
import com.yzh.utils.ordervo.R;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;
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.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* <p>
* 访问过滤器
* </p>
*
* @author qy
* @since 2019-11-08
*/
//授权
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
private TokenManager tokenManager;
private RedisTemplate redisTemplate;
public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager,RedisTemplate redisTemplate) {
super(authManager);
this.tokenManager = tokenManager;
this.redisTemplate = redisTemplate;
}
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
logger.info("================="+req.getRequestURI());
if(req.getRequestURI().indexOf("admin") == -1) {
chain.doFilter(req, res);
return;
}
UsernamePasswordAuthenticationToken authentication = null;
try {
authentication = getAuthentication(req);
} catch (Exception e) {
ResponseUtil.out(res, R.error());
}
if (authentication != null) {
SecurityContextHolder.getContext().setAuthentication(authentication);
} else {
ResponseUtil.out(res, R.error());
}
chain.doFilter(req, res);
}
//取信息判断有没有权限,进行授权处理
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
// token置于header里
String token = request.getHeader("token");
if (token != null && !"".equals(token.trim())) {
String userName = tokenManager.getUserFromToken(token);
List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
Collection<GrantedAuthority> authorities = new ArrayList<>();
for(String permissionValue : permissionValueList) {
if(StringUtils.isEmpty(permissionValue)) continue;
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
authorities.add(authority);
}
if (!StringUtils.isEmpty(userName)) {
return new UsernamePasswordAuthenticationToken(userName, token, authorities);
}
return null;
}
return null;
}
}
根据用户id获取用户菜单
//根据用户id获取用户菜单
@Override
public List<String> selectPermissionValueByUserId(String id) {
List<String> selectPermissionValueList = null;
if(this.isSysAdmin(id)) {
//如果是系统管理员,获取所有权限
selectPermissionValueList = baseMapper.selectAllPermissionValue();
} else {
selectPermissionValueList = baseMapper.selectPermissionValueByUserId(id);
}
return selectPermissionValueList;
}
@Override
public List<JSONObject> selectPermissionByUserId(String userId) {
List<Permission> selectPermissionList = null;
if(this.isSysAdmin(userId)) {
//如果是超级管理员,获取所有菜单
selectPermissionList = baseMapper.selectList(null);
} else {
selectPermissionList = baseMapper.selectPermissionByUserId(userId);
}
List<Permission> permissionList = PermissionHelper.bulid(selectPermissionList);
List<JSONObject> result = MemuHelper.bulid(permissionList);
return result;
}
/**
* 判断用户是否系统管理员
* @param userId
* @return
*/
private boolean isSysAdmin(String userId) {
User user = userService.getById(userId);
if(null != user && "admin".equals(user.getUsername())) {
return true;
}
return false;
}
给角色分配菜单(权限)
//=========================给角色分配菜单=======================
@Override
public void saveRolePermissionRealtionShipGuli(String roleId, String[] permissionIds) {
//roleId角色id
//permissionId菜单id 数组形式
//1 创建list集合,用于封装添加数据
List<RolePermission> rolePermissionList = new ArrayList<>();
//遍历所有菜单数组
for(String perId : permissionIds) {
//RolePermission对象
RolePermission rolePermission = new RolePermission();
rolePermission.setRoleId(roleId);
rolePermission.setPermissionId(perId);
//封装到list集合
rolePermissionList.add(rolePermission);
}
//添加到角色菜单关系表
rolePermissionService.saveBatch(rolePermissionList);
}