java【毕业设计】-第119期SpringBoot+shiro教育课程管理系统
【源码请到资源专栏下载】
Hi,大家好,今天分享的源码是SpringBoot+shiro教育课程后台管理系统。
该项目是一款教育的后台管理系统,包含以下功能:
系统管理:用户管理、角色管理、菜单管理
课程管理:课程管理、公共课程管理、专业课程管理、免费课程管理、类别管理、课程审核、视频管理
教师管理、导航菜单等。
备注:该项目没有前端
2、运行环境
Jdk1.8 + Tomcat8.5 + mysql + Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)
3、项目访问
访问地址:http://localhost:8081/index 用户名: admin 密码: admin
4、运行截图
5、核心代码讲解
下面主要讲一下shiro的核心配置
ShiroConfig类:首先是shiro的过滤器配置,我们需要配置好:
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
// 登录配置
shiroFilter.setLoginUrl("/login");
shiroFilter.setSuccessUrl("/");
shiroFilter.setUnauthorizedUrl("/error?code=403");
// 自定义过滤器
Map<String, Filter> filtersMap = new LinkedHashMap<>();
filtersMap.put("slf", new ShiroLoginFilter());
shiroFilter.setFilters(filtersMap);
// 拦截配置
Map<String, String> filterChainDefinitions = new LinkedHashMap<>();
filterChainDefinitions.put("/assets/**", "anon");
filterChainDefinitions.put("/favicon.ico", "anon");
filterChainDefinitions.put("/api/**", "anon");
filterChainDefinitions.put("/error", "anon");
filterChainDefinitions.put("/login", "anon");
filterChainDefinitions.put("/default/**", "anon");
filterChainDefinitions.put("/users/**", "anon");
filterChainDefinitions.put("/getFileURL/**", "anon");
filterChainDefinitions.put("/logout", "logout");
//filterChainDefinitions.put("/**", "slf,authc");
filterChainDefinitions.put("/**", "slf,user"); // 记住密码也能访问
shiroFilter.setFilterChainDefinitionMap(filterChainDefinitions);
return shiroFilter;
}
接下来是登录过滤器:ShiroLoginFilter
public class ShiroLoginFilter extends AccessControlFilter {
@Override
protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) {
return false;
}
@Override
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
Subject subject = getSubject(servletRequest, servletResponse);
if (!subject.isAuthenticated() && !subject.isRemembered()) {
if (isAjax((HttpServletRequest) servletRequest)) {
servletResponse.setContentType("application/json;charset=UTF-8");
PrintWriter out = servletResponse.getWriter();
out.write("{\"msg\": \"登录过期,请重新登录\", \"code\": 401}");
out.flush();
return false;
}
}
return true;
}
/**
* 判断是不是ajax请求
*/
private boolean isAjax(HttpServletRequest request) {
String xHeader = request.getHeader("X-Requested-With");
return (xHeader != null && xHeader.contains("XMLHttpRequest"));
}
}
再接下来,配置shiro的认证用户:UserRealm
class UserRealm extends AuthorizingRealm {
@Lazy
@Autowired
private UserTwoService userTwoService;
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String) authenticationToken.getPrincipal();
UserTwo user = userTwoService.getByUsername(username);
if (user == null) throw new UnknownAccountException(); // 账号不存在
if (user.getState() != 0) throw new LockedAccountException(); // 账号被锁定
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
}
}
接下来是shiro的认证授权
/**
* Shiro认证和授权
* Created by wangfan on 2017-04-28 09:45
*/
public class AdminRealm extends AuthorizingRealm {
@Lazy
@Autowired
private UserService userService;
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String) authenticationToken.getPrincipal();
User user = userService.getByUsername(username);
if (user == null) throw new UnknownAccountException(); // 账号不存在
if (user.getState() != 0) throw new LockedAccountException(); // 账号被锁定
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
User user = (User) SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
userService.selectRoleAndAuth(user);
// 角色
Set<String> roles = new HashSet<>();
for (Role r : user.getRoles()) {
if (r.getDeleted() == 0) roles.add(r.getRoleCode());
}
authorizationInfo.setRoles(roles);
// 权限
Set<String> permissions = new HashSet<>();
for (String auth : user.getAuthorities()) {
if (auth != null && !auth.trim().isEmpty()) permissions.add(auth);
}
authorizationInfo.setStringPermissions(permissions);
return authorizationInfo;
}
}
再接下来配置CustomizedModularRealmAuthenticator
public class CustomizedModularRealmAuthenticator extends ModularRealmAuthenticator{
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)
throws AuthenticationException {
// 判断getRealms()是否返回为空
assertRealmsConfigured();
// 强制转换回自定义的CustomizedToken
CustomizedToken customizedToken = (CustomizedToken) authenticationToken;
// 登录类型
String loginType = customizedToken.getLoginType();
// 所有Realm
Collection<Realm> realms = getRealms();
// 登录类型对应的所有Realm
Collection<Realm> typeRealms = new ArrayList<>();
for (Realm realm : realms) {
if (realm.getName().contains(loginType))
typeRealms.add(realm);
}
// 判断是单Realm还是多Realm
if (typeRealms.size() == 1)
return doSingleRealmAuthentication(typeRealms.iterator().next(), customizedToken);
else
return doMultiRealmAuthentication(typeRealms, customizedToken);
}
}
最后哦,我们这套系统分为3个角色,需要判定是哪个角色
public class CustomizedToken extends UsernamePasswordToken{
//登录类型,判断是普通用户登录,教师登录还是管理员登录
private String loginType;
public CustomizedToken(final String username,final String password,final Boolean remember, String loginType) {
super(username,password,remember);
this.loginType = loginType;
}
public String getLoginType() {
return loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
}
至此,shiro的配置就此结束。也是shiro在这个项目里的核心配置。