使用SHIRO的步驟:
1,導入jar
2,配置web.xml
3,建立dbRelm
4,在Spring中配置
?
添加所需jar包:
- <!--Apache?Shiro所需的jar包-->????
- ????<dependency>????
- ??????<groupId>org.apache.shiro</groupId>????
- ??????<artifactId>shiro-core</artifactId>????
- ??????<version>1.2.2</version>????
- ????</dependency>????
- ????<dependency>????
- ??????<groupId>org.apache.shiro</groupId>????
- ??????<artifactId>shiro-web</artifactId>????
- ??????<version>1.2.2</version>????
- ????</dependency>????
- ????<dependency>????
- ??????<groupId>org.apache.shiro</groupId>????
- ??????<artifactId>shiro-spring</artifactId>????
- ??????<version>1.2.2</version>????
- ????</dependency>???
- ??</dependencies> ?
?
web.xml中配置shrio的過濾器:
- <!--?Shiro配置?-->????
- ??<filter>????
- ????<filter-name>shiroFilter</filter-name>????
- ????<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>????
- ??</filter>????
- ??<filter-mapping>????
- ????<filter-name>shiroFilter</filter-name>????
- ????<url-pattern>/*</url-pattern>????
- ??</filter-mapping> ?
權限控制類:
public class ShiroRealm extends AuthorizingRealm {
private static final Logger log = Logger.getLogger(ShiroRealm.class);
@Autowired
private SysUsersService userService;
@Autowired
private SysUserRolesService userRoleService;
@Autowired
private SysRolePermissionsService sysRolePermissionsService;
@Autowired
private SysPermissionsService sysPermissionsService;
/**
* 為當前登錄的Subject授予角色和權限
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 獲取當前登錄的用戶名,等價于(String)principals.fromRealm(this.getName()).iterator().next()
String currentUsername = (String) super.getAvailablePrincipal(principals);
List<String> roleList = new ArrayList<String>();
List<String> permissionList = new ArrayList<String>();
// 從數據庫中獲取當前登錄用戶的詳細信息
// roleList.add("admin");
SysUsers user = userService.getUserByUsername(currentUsername);
if(null != user){
//超級用戶直接獲取所有權限
if(user.getIsAdministrator()==1){
List<SysPermissions> pList = sysPermissionsService.getAll();
if(pList!=null && pList.size()>0){
for (SysPermissions p: pList) {
permissionList.add(p.getPermissionKey());
}
}
}else {
//獲取用戶角色列表
List<SysUserRoles> roles = userRoleService.getUserRolesByUserName(currentUsername);
List<Integer> roleIdList = new ArrayList<>();
if (roles != null&&roles.size()>0) {
for (SysUserRoles role : roles) {
System.out.println(role.getRoleKey());
log.debug("授予角色>>>" + role.getRoleKey());
roleList.add(role.getRoleKey());
roleIdList.add(role.getRoleId());
}
}
//獲取用戶權限列表
List<SysRolePermissions> permissionsList = sysRolePermissionsService.getPermissionsByRoleIds(roleIdList);
if (permissionsList != null && permissionsList.size() > 0) {
for (SysRolePermissions pmss : permissionsList) {
if (!StringUtils.isBlank(pmss.getPermissionKey())) {
log.debug("授予權限>>>>" + pmss.getPermissionKey());
permissionList.add(pmss.getPermissionKey());
}
}
}
}
}else {
throw new AuthorizationException();
}
// if (null != user) {
// // 實體類User中包含有用戶角色的實體類信息
// if (null != user.getRoles() && user.getRoles().size() > 0) {
// // 獲取當前登錄用戶的角色
// for (Role role : user.getRoles()) {
// if (!StringUtils.isBlank(role.getName())) {
// log.debug("授予角色>>>" + role.getName());
// roleList.add(role.getName());
// }
// }
// }
// // 實體類User中包含有角色權限的實體類信息
// if (null != user.getPermissions() && user.getPermissions().size() > 0) {
// for (Permission pmss : user.getPermissions()) {
// if (!StringUtils.isBlank(pmss.getPermission())) {
// log.debug("授予權限>>>>" + pmss.getPermission());
// permissionList.add(pmss.getPermission());
// }
// }
// }
// } else {
// throw new AuthorizationException();
// }
// 為當前用戶設置角色和權限
SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
simpleAuthorInfo.addRoles(roleList);
simpleAuthorInfo.addStringPermissions(permissionList);
return simpleAuthorInfo;
}
/**
* 驗證當前登錄的Subject
* 認證回調函數,登錄時調用.
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
throws AuthenticationException {
// 獲取基于用戶名和密碼的令牌
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
SysUsers user = userService.getUserByUsername(token.getUsername());
AuthenticationInfo authcInfo = null;
if (user == null) {
throw new UnknownAccountException();// 未知賬戶
}
else if(!user.getPassword().equals(ParseMD5.parseStrToMd5L32(String.valueOf(token.getPassword())))){
throw new UnknownAccountException();// 賬戶密碼錯誤,與管理員聯系
}
else if (user.getStatus() == 0) {
throw new LockedAccountException();// 賬戶已鎖定,與管理員聯系
}
else {
authcInfo = new SimpleAuthenticationInfo(user.getUsername(),
token.getPassword(),
getName());
this.setSession("currentUser", user.getUsername());
}
return authcInfo;
}
/**
* 更新授權信息緩存
*/
public void clearCachedAuthorizationInfo(String principal) {
SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
clearCachedAuthorizationInfo(principals);
}
/**
* ShiroSession設置
*
* @see 使用時直接用HttpSession.getAttribute(key)就可以取到
*/
private void setSession(Object key, Object value) {
Subject currentUser = SecurityUtils.getSubject();
if (null != currentUser) {
Session session = currentUser.getSession();
if (null != session) {
session.setAttribute(key, value);
}
}
}
}
在spring的配置文件中配置:新建spring-shrio.xml文件:
- <?xml?version="1.0"?encoding="UTF-8"??>??
- <beans?xmlns="http://www.springframework.org/schema/beans"??
- ???????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??
- ???????xmlns:aop="http://www.springframework.org/schema/aop"??
- ???????xmlns:tx="http://www.springframework.org/schema/tx"??
- ???????xmlns:context="http://www.springframework.org/schema/context"??
- ???????xsi:schemaLocation="??
- http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd??
- http://www.springframework.org/schema/tx?http://www.springframework.org/schema/tx/spring-tx.xsd??
- http://www.springframework.org/schema/aop?http://www.springframework.org/schema/aop/spring-aop.xsd??
- http://www.springframework.org/schema/context?http://www.springframework.org/schema/context/spring-context.xsd">??
- ??
- ????<!--?配置權限管理器?-->??
- ????<bean?id="securityManager"?class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">????
- ????????<!--?ref對應我們寫的realm??MyShiro?-->??
- ????????<property?name="realm"?ref="myShiro"/>????
- ????????<!--?使用下面配置的緩存管理器?-->??
- ????????<property?name="cacheManager"?ref="cacheManager"/>????
- ????</bean>??
- ??????
- ????<!--?配置shiro的過濾器工廠類,id-?shiroFilter要和我們在web.xml中配置的過濾器一致?-->??
- ????<bean?id="shiroFilter"?class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">???
- ????????<!--?調用我們配置的權限管理器?-->???
- ????????<property?name="securityManager"?ref="securityManager"/>???
- ????????<!--?配置我們的登錄請求地址?-->???
- ????????<property?name="loginUrl"?value="/login"/> ? ?<!--login方法我們自定義一個控制器-->
- ????????<!--?配置我們在登錄頁登錄成功后的跳轉地址,如果你訪問的是非/login地址,則跳到您訪問的地址?-->??
- ????????<property?name="successUrl"?value="/main"/>????
- ????????<!--?如果您請求的資源不再您的權限范圍,則跳轉到/unauthorized請求地址?-->??
- ????????<property?name="unauthorizedUrl"?value="/unauthorized"/>????
- ????????<!--?權限配置?-->??
- ????????<property?name="filterChainDefinitions">????
- ????????????<value>????
- ????????????????<!--?anon表示此地址不需要任何權限即可訪問?-->??
- ????????????????/static/**=anon??
- ????????????????<!--?perms[user:query]表示訪問此連接需要權限為user:query的用戶?-->??
- ????????????????/user=perms[user:query]??
- ????????????????<!--?roles[manager]表示訪問此連接需要用戶的角色為manager?-->??
- ????????????????/user/add=roles[manager]??
- ????????????????/user/del/**=roles[admin]??
- ????????????????/user/edit/**=roles[manager]??
- ????????????????<!--所有的請求(除去配置的靜態資源請求或請求地址為anon的請求)都要通過登錄驗證,如果未登錄則跳到/login-->????
- ????????????????/**?=?authc??
- ????????????</value>????
- ????????</property>????
- ????</bean>??
- ??????
- ? ? ?<bean id="myShiro" class="ShrioRealm"/><!--權限控制類的全類名-->
- ????<bean?id="cacheManager"?class="org.apache.shiro.cache.MemoryConstrainedCacheManager"?/>????
- ????<bean?id="lifecycleBeanPostProcessor"?class="org.apache.shiro.spring.LifecycleBeanPostProcessor"?/>???
- ??????
- </beans>??
對于登錄,未授權,錯誤的請求url寫上請求控制處理方法:
package net.lcheng.manage.controller;
import net.lcheng.commons.utils.ParseMD5;
import net.lcheng.manage.utils.ControllerUtils;
import net.lcheng.manage.vo.PasswordModel;
import net.lcheng.model.SysUsers;
import net.lcheng.service.SysPermissionsService;
import net.lcheng.service.SysUsersService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.validation.Valid;
@Controller
public class HomeController {
@Autowired
private SysUsersService usersService;
@Autowired
private SysPermissionsService permissionsService;
@RequestMapping("/main")
// @RequiresRoles("admin")
// @RequiresPermissions("user:create")
public String main(Model model) throws Exception {
ControllerUtils.common(model,permissionsService,"");
return "main";
}
/**權限不足錯誤頁面*/
@RequestMapping("/unauthorized")
public String unauthorized(Model model){
Subject currentUser = SecurityUtils.getSubject();//獲取當前用戶
if(currentUser.isAuthenticated()) {
model.addAttribute("userName",currentUser.getPrincipals());
}
return "unauthorized";
}
/**錯誤頁面*/
@RequestMapping("/error")
public String error(Model model){
Subject currentUser = SecurityUtils.getSubject();//獲取當前用戶
if(currentUser.isAuthenticated()) {
model.addAttribute("userName",currentUser.getPrincipals());
}
return "error";
}
@RequestMapping(value = "/change_pwd",method = RequestMethod.GET)
public String changePwd(Model model){
model.addAttribute("PasswordModel",new PasswordModel());
ControllerUtils.common(model,permissionsService,"");
return "change_pwd";
}
@RequestMapping(value = "/change_pwd",method = RequestMethod.POST)
public String changePwdPost(Model model,@Valid @ModelAttribute("PasswordModel") PasswordModel user, BindingResult result){
Subject currentUser = SecurityUtils.getSubject();//獲取當前用戶
ControllerUtils.common(model,permissionsService,"");
if (result.hasErrors()) {
return "change_pwd";
}
SysUsers sysUser = usersService.getUserByUsername(currentUser.getPrincipals().toString());
if(sysUser!=null) {
if(!sysUser.getPassword().equals(ParseMD5.parseStrToMd5L32(user.getOldPwd()))){
model.addAttribute("error", "原密碼錯誤");
return "change_pwd";
}
if(!user.getNewPwd().equals(user.getRePwd())){
model.addAttribute("error", "二次密碼不一致");
return "change_pwd";
}
if(ParseMD5.parseStrToMd5L32(user.getNewPwd()).equals(ParseMD5.parseStrToMd5L32(user.getOldPwd()))){
model.addAttribute("error", "新密碼和原密碼一樣");
return "change_pwd";
}
usersService.changePassword(sysUser.getId(), ParseMD5.parseStrToMd5L32(user.getNewPwd()));
model.addAttribute("error", "密碼修改成功,請使用新密碼重新登錄!");
}else{
model.addAttribute("error", "用戶不存在");
}
return "change_pwd";
}
}
package net.lcheng.manage.controller;
import net.lcheng.commons.utils.ParseMD5;
import net.lcheng.manage.vo.LoginEntity;
import net.lcheng.model.SysUsers;
import net.lcheng.service.SysUsersService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.validation.Valid;
/**
* Created by qiliping on 15/12/1.
* 登錄Controller
*/
@Controller
public class LoginController {
@Autowired
private SysUsersService sysUsersService;
/**
* 登錄GET
*/
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String Index(Model model) {
if (!model.containsAttribute("LoginEntity")) {
model.addAttribute("LoginEntity", new LoginEntity());
}
return "login";
}
/***
* 用戶登陸
* <p>注解配置,只允許POST提交到該方法
*
* @param username
* @param password
* @return
*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(Model model, @Valid @ModelAttribute("LoginEntity") LoginEntity user, BindingResult result) {
if (result.hasErrors()) {
return "login";
}
SysUsers userModel = sysUsersService.getUserByUsername(user.getUsername());
if (userModel != null) {
String inputPwd = ParseMD5.parseStrToMd5L32(user.getPassword());
if (!userModel.getPassword().equals(inputPwd)) {
model.addAttribute("error", "登錄密碼錯誤");
return "login";
}
if (userModel.getStatus() != 1) {
model.addAttribute("error", "無效的用戶");
return "login";
}
//登錄成功
SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), user.getPassword()));
return "redirect:/main";
} else {
model.addAttribute("error", "用戶不存在");
return "login";
}
}
/***
* 退出
* @param model
* @return
*/
@RequestMapping(value = "logout")
public String logout(Model model) {
SecurityUtils.getSubject().logout();
return "redirect:/login";
}
/***
* 驗證參數是否為空
*
* @param params
* @return
*/
private boolean checkParams(String[] params) {
for (String param : params) {
if (param == "" || param == null || param.isEmpty()) {
return false;
}
}
return true;
}
}