public class Auth implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 大模块code,例如咨询类功能
*/
private String resourceCode;
/**
* 细化功能,例如查询咨询列表
*/
private String actionCode;
/**
* 是否赋权
*/
private String hasThisAuth;
public Auth() {}
public Auth(String resourceCode, String resourceName, String actionCode,
String actionName, String actionURL, String remark,
String hasThisAuth, String roleCombined) {
this.resourceCode = resourceCode;
this.actionCode = actionCode;
this.hasThisAuth = hasThisAuth;
}
public String getResourceCode() {
return resourceCode;
}
public void setResourceCode(String resourceCode) {
this.resourceCode = resourceCode;
}
public String getActionCode() {
return actionCode;
}
public void setActionCode(String actionCode) {
this.actionCode = actionCode;
}
public String getHasThisAuth() {
return hasThisAuth;
}
public void setHasThisAuth(String hasThisAuth) {
this.hasThisAuth = hasThisAuth;
}
}
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 角色名称
*/
private String name;
/**
* 角色code
*/
private String code;
/**
* 拥有的权限列表
*/
private List auths;
public Role() {
// nothing
}
//region getter setter
public List getAuths() {
return auths;
}
public void setAuths(List auths) {
this.auths = auths;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
3.CurrnetUser用户信息封装类
public class CurrentUser implements Serializable{
private static final long serialVersionUID = 1L;
private long id;
/**
* 姓名
*/
private String name;
/**
* 密码
*/
private String password;
/**
* 部门
*/
private String department;
private Role role;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
public class UserAuthentication implements Authentication {
/**
* 当前用户信息
*/
private CurrentUser user;
public UserAuthentication(CurrentUser user){
if(user != null){
this.user = user;
}else{
CurrentUser guest = new CurrentUser();
this.user = guest;
}
}
/**
* 获取当前用户权限列表
* 注:这里用户没有实际用到角色,代码中将角色也赋予成了权限
* @return
*/
@Override
public Collection extends GrantedAuthority> getAuthorities() {
List authorities = new ArrayList<>();
/**
* 获取用户角色的对应的权限列表
*/
if(user.getRole() != null){
Role userRole = user.getRole();
// add "AUTH" 规则:ResourceCode:ActionCode
for(Auth userAuth : userRole.getAuths()){
// "1" - has this auth | "0" - do not have this auth
if("1".equals(userAuth.getHasThisAuth())){
GrantedAuthority mainAuth = (GrantedAuthority) ()
-> userAuth.getResourceCode() + ":" + userAuth.getActionCode();
authorities.add(mainAuth);
}
}
// add "ROLE" 规则 ROLE_code
GrantedAuthority mainAuth = (GrantedAuthority) ()
-> "ROLE_" + userRole.getCode();
authorities.add(mainAuth);
}
return authorities;
}
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getDetails() {
return null;
}
@Override
public CurrentUser getPrincipal() {
return user;
}
@Override
public boolean isAuthenticated() {
return true;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName() {
return user.getName() == null ? "guest" : user.getName();
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class ApiBaseMessage {
private boolean success;
private String statusCode = "";
private T data;
private String error = "";
public ApiBaseMessage(){
}
// constructor for success and data
public ApiBaseMessage(T data){
this.success = true;
this.data = data;
}
// constructor for app server error message
public ApiBaseMessage(String statusCode, String errorDescribe){
this.statusCode = statusCode;
this.error = errorDescribe;
}
// constructor from a failed ApiBaseMessage
public ApiBaseMessage(ApiBaseMessage> msg) {
this.statusCode = msg.getStatusCode();
this.error = msg.getError();
this.success = false;
this.data = null;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getStatusCode() {
return statusCode;
}
public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
@Override
public String toString() {
return "ApiBaseMessage{" +
"success=" + success +
", statusCode='" + statusCode + '\'' +
", data=" + data +
", error='" + error + '\'' +
'}';
}
}
@RestController
@RequestMapping(value = "/api/service/account")
public class UserController {
/**
* 登录功能
* @return
*/
@RequestMapping(value = "/login", method = {RequestMethod.GET})
public ApiBaseMessage login(){
//TODO 调用第三方权限认证接口
/**
* 用户信息
*/
CurrentUser currentUser = new CurrentUser();
currentUser.setName("王坤");
currentUser.setDepartment("研发部");
/**
* 权限信息
*/
List auths = new ArrayList<>();
Auth auth = new Auth();
auth.setResourceCode("userinfo");
auth.setActionCode("query");
auth.setHasThisAuth("1");
auths.add(auth);
/**
* 角色信息
*/
Role role = new Role();
role.setAuths(auths);
currentUser.setRole(role);
SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(currentUser));
return new ApiBaseMessage("登录成功");
}
/**
* 查询功能
* @return
*/
@RequestMapping(value = "/query", method = {RequestMethod.GET})
public ApiBaseMessage query(){
/**
* 获取登录用户信息
*/
CurrentUser principal = (CurrentUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return new ApiBaseMessage("查询成功,亲爱的"+principal.getName());
}
}
创建SecurityConfig权限配置类
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// csrf 关闭,保证 api 调用无须传递 csrf token
// http.antMatcher("/api/**")
// .csrf().disable().
http.authorizeRequests()
.antMatchers("/api/service/account/login").permitAll()//这些请求放行,通常是登录请求和不需要登录就能调用的接口
.antMatchers("/api/service/account/query").hasAuthority("userinfo:query")//需要相关的权限
.anyRequest().authenticated()//其他请求校验
.and()//并且 如下校验
.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {//异常处理,当匿名登录被拦截时走的方法
ObjectMapper mapper = new ObjectMapper();
String errorMsg;
if (request.getRequestURI().startsWith("/api/internal/")) {
errorMsg = mapper.writeValueAsString(new ApiBaseMessage<>("10002", "非法的请求来源:" + request.getRemoteHost()));
} else {
errorMsg = mapper.writeValueAsString(new ApiBaseMessage<>("10002", "请先登录"));
}
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_OK);
response.setCharacterEncoding("UTF-8");
response.getWriter().write(errorMsg);
})
;
// 子线程继承父线程 spring security context
//SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
}
按照第三步配置,预期情况如下:
1.直接调用query接口,提示请登录
2.调用登录接口成功后,再次调用query接口能成功,并且能读取到登录用户的信息
启动项目,开始测试:
http://localhost:8082/api/service/account/query
http://localhost:8082/api/service/account/login
http://localhost:8082/api/service/account/query
测试通过。
后续小伙伴可以把登录接口中 权限设置为0,再试试,或者把SecurityConfig类,对于query接口的权限进行更改再进行相关测试。
参考第二篇博客
https://blog.csdn.net/wk2yangyang/article/details/118541553