springmvc集成shiro例子

时间:2024-06-26 09:35:08

仅供参考

仅供参考

登录部分

代码:

    @RequestMapping(value = "/login", method = RequestMethod.GET)
@ResponseBody
public Map<String, Object> login(HttpServletRequest request)
{
Map<String, Object> resultMap = new LinkedHashMap<String, Object>();
try
{
ShiroToken token = new ShiroToken("admin", "21232f297a57a5a743894a0e4a801fc3");
token.setRememberMe(false);
SecurityUtils.getSubject().login(token);
ShiroToken token2 = (ShiroToken) SecurityUtils.getSubject().getPrincipal(); logger.info(token2.getUsername() + "," + token2.getPswd()); resultMap.put("status", 200);
resultMap.put("message", "登录成功"); /**
* 获取登录之前的地址
*/
SavedRequest savedRequest = WebUtils.getSavedRequest(request);
String url = null;
if (null != savedRequest)
{
url = savedRequest.getRequestUrl();
}
// 跳转地址
resultMap.put("back_url", url);
}
catch (DisabledAccountException e)
{
resultMap.put("status", 500);
resultMap.put("message", "帐号已经禁用。");
}
catch (Exception e)
{
resultMap.put("status", 500);
resultMap.put("message", "帐号或密码错误");
}
return resultMap;
}

注意几点:

1、登录密码记得加密,一般存在数据库中的密码是加密过的。

2、真正开始执行登录操作的是SecurityUtils.getSubject().login(token),这个方法会调用org.apache.shiro.realm.AuthorizingRealm的doGetAuthenticationInfo方法进行登录认证:

3、出错异常记得捕获

登录验证部分

代码如下:

   @Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0)
{
ShiroToken token = (ShiroToken) arg0;
String username = token.getUsername(); // 根据username从数据库查找用户,得到密码
// 假设找到的用户如下
// User user = userService.findByUsername(username)
User user = new User();
user.setName(username);
user.setPassword("21232f297a57a5a743894a0e4a801fc3"); // 数据库中的密码md5加密的 if (null == user)
{
throw new AccountException("username is not exist");
}
else if (!user.getPassword().equals(token.getPswd()))
{
throw new AccountException("password is not right");
}
else
{
// 登陆成功
logger.info("{} login success.", username);
}
return new SimpleAuthenticationInfo(arg0, user.getPassword(), username);
}

注意几点:

1、一般会根据username从数据库中查找该用户,得到密码

2、进行密码校验,判断一致性

3、根据获取到的用户信息,也可以进行其它判断,如用户是否激活,是否被禁用等

授权部分

代码如下:

    @Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
{
ShiroToken token = (ShiroToken) SecurityUtils.getSubject().getPrincipal();
String username = token.getUsername();
logger.info(username + "授权..."); // 从数据库中查找该用户的角色和权限
SimpleAuthorizationInfo sainfo = new SimpleAuthorizationInfo(); Set<String> roles = new HashSet<String>();
roles.add("admin");
//roles.add("role1");
Set<String> permissions = new HashSet<String>();
permissions.add("add");
permissions.add("delete");
sainfo.setRoles(roles);
sainfo.setStringPermissions(permissions);
return sainfo;
}

注意,一般是根据用户名从数据库中查找该用户的角色和权限,进行授权;当然其它途径也是可以的,如webservice接口,配置文件等获取用户权限。

权限拦截配置

如下:

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"></property>
<property name="loginUrl" value="/security/view/login"></property>
<property name="successUrl" value="/successUrl"></property>
<!-- 用户访问未对其授权的资源时,所显示的连接 -->
<property name="unauthorizedUrl" value="/unauthorizedUrl"></property>
<property name="filters">
<map>
<entry key="anyRoles">
<bean class="cn.edu.hdu.ssd.core.shiro.AnyRolesAuthorizationFilter" />
</entry>
</map>
</property>
<property name="filterChainDefinitions">
<value>
/security/**=anon
/test/**=roles[role1]
/users/**=anyRoles[admin,role1]
/**=authc
</value>
</property>
</bean>

根据用户的角色或权限来配置对应匹配的访问路径;

访问路径匹配任意角色

默认情况下,配置权限控制的时候,如

/test/**=roles[role1,admin]

结果是需要用户同时拥有role1和admin权限才能访问/test/**路径,这往往不符合我们的需求,

大部分情况,我们希望的是用户拥有role1和admin任一角色即可。

那么可以这样修改,编写一个过滤器:

public class AnyRolesAuthorizationFilter extends AuthorizationFilter
{ // private Logger logger = LoggerFactory.getLogger(ShiroCasAuthFilter.class);
@Override
protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue)
throws Exception
{
Subject subject = getSubject(req, resp);
String[] rolesArray = (String[]) mappedValue; if (rolesArray == null || rolesArray.length == 0)
{
return true;
}
for (int i = 0; i < rolesArray.length; i++)
{
if (subject.hasRole(rolesArray[i]))
{
return true;
}
}
return false;
}
}

配置shiroFilter bean的filters属性,如下,

        <property name="filters">
<map>
<entry key="anyRoles">
<bean class="cn.edu.hdu.ssd.core.shiro.AnyRolesAuthorizationFilter" />
</entry>
</map>
</property>

最后,权限拦截配置可以这样配:

/test/**=anyRoles[admin,role1]

示例源码参考

https://github.com/peterchenhdu/spring-shiro-demo

测试

登录:http://localhost:8080/ssd/security/login ----->角色:admin,用户名:admin,密码:21232f297a57a5a743894a0e4a801fc3
权限测试:http://localhost:8080/ssd/users ----->访问成功
权限测试:http://localhost:8080/ssd/test/access ----->访问失败,无访问权限
换个角色登录,修改UserRealm.java里的角色为roler1,重新登录http://localhost:8080/ssd/security/login
权限测试:http://localhost:8080/ssd/users ----->访问成功
权限测试:http://localhost:8080/ssd/test/access ----->访问成功