代码实现
自定义Realm
@Component("myRealm")
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 授权方法,在配有缓存的情况下,只加载一次。
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
List<Authority> authorities = shiroUser.getAuthorities();
Set<String> roles = new HashSet<String>();
for (Authority authority : authorities){
roles.add(authority.getName());
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(roles);
return info;
}
/**
* 登录认证
* @param token
* @return
* @throws AuthenticationException
*/
@Transactional
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken uptoken = (UsernamePasswordToken) token;
String username = uptoken.getUsername();
User user = userService.findUserByLoginName(username);
if( user == null ) {
throw new UnknownAccountException("用户名"+username+"不存在.");
}
if (user.getEnabled() != 1){
throw new LockedAccountException(user.getName()+"被锁定");
}
ShiroUser principal = new ShiroUser();
String userInfo = user.getName()+"("+user.getRole().getName()+")";
principal.setUserInfo(userInfo);
principal.setAuthorities(user.getRole().getAuthorities());
Object hashedCredentials = user.getPassword();
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());
String realmName = getName();
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal,hashedCredentials, credentialsSalt,realmName);
return info;
}
public class ShiroUser{
//userName(roleName)
private String userInfo;
private List<Authority> authorities;
public List<Authority> getAuthorities() {
return authorities;
}
public void setAuthorities(List<Authority> authorities) {
this.authorities = authorities;
}
public String getUserInfo() {
return userInfo;
}
public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
}
}
/**
* 初始化 使用MD5加密
*/
@PostConstruct
public void initCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
// 加密1024次
hashedCredentialsMatcher.setHashIterations(1024);
//
this.setCredentialsMatcher(hashedCredentialsMatcher);
}
}
Main方法生成salt 和password
// 利用shiro提供的随机数生成类、生成随机数,用于盐值加密
SecureRandomNumberGenerator secureRandomNumberGenerator =
new SecureRandomNumberGenerator();
String str = secureRandomNumberGenerator.nextBytes().toBase64();
System.out.println(str);//
String algorithmName = "MD5";
Object source = "123456";
//盐值 NWJtcFg3VFNtNEdEWTh6UUtoSTRkdz09
ByteSource salt = ByteSource.Util.bytes(str);
int hashIterations = 1024;
Object result = new SimpleHash(algorithmName,source,salt,hashIterations);
System.out.println(result);//数据库中密码 b9aa43cfb15649c932ac647df54101a7
LoginController.java
@RequestMapping(value = "/login",method = RequestMethod.POST)
private String login(HttpServletRequest request,Modelmodel,
@RequestParam(name = "username",required = false) String username, @RequestParam(name = "password",required = false) String password, RedirectAttributes attributes){
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
//usernamePasswordToken.setRememberMe(false);
Subject subject = SecurityUtils.getSubject();
String message = null;
if(!subject.isAuthenticated()){
try {
subject.login(usernamePasswordToken);
} catch (UnknownAccountException ex) {//用户名没有找到
//ex.printStackTrace();
message = "用户名不存在";
} catch (IncorrectCredentialsException ex) {//用户名密码不匹配
// ex.printStackTrace();
message = "用户名和密码不匹配";
}catch (LockedAccountException lae) {// 用户被锁定
//lae.printStackTrace();
message = "用户被锁定";
}catch (AuthenticationException e) {//其他的登录错误
e.printStackTrace();
}
if(message!=null){
attributes.addFlashAttribute("message", message);
return "redirect:/shiro-login";
}
}
return "redirect:/success";
}
基于注解的权限设置
在controller list方法上加上 @RequiresRoles(value={"admin"}) 说明此方法需要有admin角色的用户才可以操作。
@RequiresRoles(value={"admin"})
@RequestMapping(value = "/list", method= RequestMethod.GET)
public String list(Model model, HttpServletRequest request){
List<User> userList=userService.listAll(0,10);
model.addAttribute("list", userList);
return "user/userList";
}
我们用两个用户来测试
可以看到admin用户可以访问list页面,而gx因为没有admin的角色,访问失败。
附:数据库关系图
总结:本文通过例子,简单实现了权限的控制,相比与spring secruity的复杂配置,shiro更加简单。